@dwack1234/arabic-keyboard-nextjs
v1.0.7
Published
A full-featured Arabic keyboard component for Next.js and React applications
Maintainers
Readme
Arabic Keyboard for Next.js
A fully-featured, customizable Arabic virtual keyboard web application built with Next.js 16, React 19, and TypeScript. Features an interactive virtual keyboard for typing Arabic text with support for tashkeel (diacritical marks), Alif variants, and real-time word display.
Version: 2.0.0
Last Updated: October 27, 2025
📑 Table of Contents
- Features
- Getting Started
- Development Commands
- Architecture
- Component API
- Keyboard Layouts
- Settings & Configuration
- Testing
- Browser Support
- Contributing
- License
✨ Features
Core Functionality
- ✅ Dual Language Support - Arabic (KBDA1) and English (QWERTY) layouts
- ✅ Real-time Character Input - Character-by-character callback API
- ✅ Comprehensive Callback System - 15+ event callbacks for complete control
- ✅ Standalone or Integrated - Works as pure input device or with text areas
- ✅ Modifier Keys - Shift, Ctrl, Alt support
- ✅ Special Characters - Full Tashkeel (diacritics) support
- ✅ Sound Effects - Keypress, clear, and UI sounds (optional)
- ✅ Responsive Design - Works on all screen sizes
- ✅ Floating Words Display - Completed words float across the screen with random positions and colors
Advanced Features
- 🎨 Extensive Customization - 100+ settings across 11 categories
- 🎵 Sound System - Multiple sound profiles with volume control
- 📱 Touch Optimized - Smooth touch interactions
- ♿ Accessibility - ARIA labels and keyboard navigation
- 🌈 Theme Support - Multiple built-in themes
- ⚡ Performance - Optimized rendering with React 19
- 📦 TypeScript - Full type safety with comprehensive interfaces
- 🧪 Tested - Unit tests with Jest and React Testing Library
🚀 Getting Started
Prerequisites
- Node.js 18+
- npm, yarn, or pnpm
Installation
# Clone the repository
git clone https://github.com/d-wack/arabic-keyboard-nextjs.git
cd arabic-keyboard-nextjs
# Install dependencies
npm install
# Start development server
npm run devOpen http://localhost:3000 to see the application.
🛠️ Development Commands
Running the Application
npm run dev # Start development server (http://localhost:3000)
npm run build # Build for production
npm start # Start production serverTesting
npm test # Run all tests with Jest
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage reportLinting
npm run lint # Run ESLint🏛️ Architecture
The application follows a clean component-based architecture:
Main Components
src/app/page.tsx- Main page with demo selector and three demo modes:- Original: Floating words demo
- Real-Time: Character-by-character display with statistics
- Form: Multi-field form integration example
src/components/ArabicKeyboard.tsx- Virtual keyboard component- Supports Arabic (KBDA1) and English (QWERTY) layouts
- Three input modes: Normal, Shift (tashkeel), Ctrl (Alif variants)
- Comprehensive callback API for integration
- Physical keyboard support with visual feedback
src/components/WordDisplay.tsx- Floating word display- Shows completed words as floating elements
- Random positions, sizes, colors, and opacity
- Click to remove words
src/context/SettingsContext.tsx- Settings management- Centralized settings with localStorage persistence
- 11 categories: appearance, layout, behavior, sound, animations, etc.
Key Features
- Callback-based API: Character input, backspace, enter, clear, modifiers
- Dual Modes: Standalone (internal state) or Integrated (external state via callbacks)
- Settings System: 100+ customizable settings with live preview
- Language Toggle: Alt+L keyboard shortcut or UI button
📚 Component API
ArabicKeyboard Props
interface ArabicKeyboardProps {
// ===== REQUIRED =====
isVisible: boolean; // Control keyboard visibility
onToggle: () => void; // Toggle handler
// ===== CALLBACK API =====
callbacks?: KeyboardCallbacks; // Event callbacks (see below)
mode?: 'standalone' | 'integrated'; // Default: 'standalone'
// ===== TARGET ELEMENT (Optional) =====
targetInputRef?: React.RefObject<HTMLInputElement | HTMLTextAreaElement>;
targetInputId?: string;
autoFocusTarget?: boolean; // Default: false
syncWithTarget?: boolean; // Default: true
// ===== CONTROLLED MODE (Optional) =====
value?: string; // External text value
onValueChange?: (value: string) => void;
cursorPosition?: number;
onCursorPositionChange?: (position: number) => void;
// ===== BEHAVIOR =====
insertMode?: 'append' | 'cursor'; // Default: 'cursor'
textChangeDebounce?: number; // Default: 0 (ms)
emitEventsInStandaloneMode?: boolean; // Default: false
// ===== LEGACY =====
onWordComplete?: (word: string) => void; // Backward compatible
}Callback API
The callback API provides 15+ events for complete control over keyboard interactions:
interface KeyboardCallbacks {
// ===== CHARACTER INPUT =====
onCharacterInput?: (
char: string,
metadata: InputMetadata
) => void;
onBackspace?: (
deletedText: string,
metadata: Omit<InputMetadata, 'keyType'>
) => void;
onTextChange?: (
newText: string,
previousText: string,
changeType: 'insert' | 'delete' | 'clear' | 'external',
metadata: InputMetadata
) => void;
// ===== WORD & SUBMISSION =====
onWordComplete?: (word: string) => void;
onEnter?: (
currentText: string,
metadata: Omit<InputMetadata, 'keyType'>
) => void;
onClear?: (
clearedText: string,
metadata: Omit<InputMetadata, 'keyType'>
) => void;
// ===== MODIFIER KEYS =====
onShiftToggle?: (isPressed: boolean) => void;
onCtrlToggle?: (isPressed: boolean) => void;
onAltToggle?: (isPressed: boolean) => void;
// ===== CURSOR CONTROL =====
onCursorMove?: (
newPosition: number,
oldPosition: number
) => void;
onTextSelect?: (
selectedText: string,
startPos: number,
endPos: number
) => void;
// ===== KEYBOARD STATE =====
onKeyboardOpen?: () => void;
onKeyboardClose?: () => void;
onLanguageChange?: (
newLanguage: 'ar' | 'en',
previousLanguage: 'ar' | 'en'
) => void;
// ===== SPECIAL KEYS =====
onSpacePressed?: () => void;
onTabPressed?: () => void;
}InputMetadata
Every callback includes metadata about the input context:
interface InputMetadata {
keyType: 'letter' | 'number' | 'tashkeel' | 'special' | 'modifier';
language: 'ar' | 'en';
timestamp: number;
cursorPosition: number;
textLength: number;
isShiftPressed: boolean;
isCtrlPressed: boolean;
isAltPressed: boolean;
insertMode: 'append' | 'cursor';
}💡 Usage Examples
See the live examples in the application:
- Original Demo: Floating words display (default view)
- Real-Time Demo: Character tracking with statistics
- Form Demo: Multi-field form integration
Basic Integration
Example 1: Real-Time Display
'use client';
import { useState, useMemo } from 'react';
import ArabicKeyboard from '@/components/ArabicKeyboard';
import type { KeyboardCallbacks } from '@/types/keyboard.types';
export default function RealTimeExample() {
const [displayText, setDisplayText] = useState('');
const [eventLog, setEventLog] = useState<string[]>([]);
const [stats, setStats] = useState({
totalKeystrokes: 0,
letters: 0,
numbers: 0,
tashkeel: 0,
});
const callbacks: KeyboardCallbacks = useMemo(() => ({
onCharacterInput: (char, metadata) => {
setDisplayText(prev => prev + char);
setStats(prev => ({
...prev,
totalKeystrokes: prev.totalKeystrokes + 1,
letters: metadata.keyType === 'letter' ? prev.letters + 1 : prev.letters,
numbers: metadata.keyType === 'number' ? prev.numbers + 1 : prev.numbers,
tashkeel: metadata.keyType === 'tashkeel' ? prev.tashkeel + 1 : prev.tashkeel,
}));
},
onBackspace: (deletedText) => {
setDisplayText(prev => prev.slice(0, -deletedText.length));
},
onEnter: () => {
setDisplayText(prev => prev + '\n');
},
onClear: () => {
setDisplayText('');
},
onWordComplete: (word) => {
setEventLog(prev => [...prev, `Word: ${word}`]);
},
}), []);
return (
<div>
<div className="display" dir="rtl">
{displayText || 'Start typing...'}
</div>
<div className="stats">
<p>Keystrokes: {stats.totalKeystrokes}</p>
<p>Letters: {stats.letters}</p>
<p>Numbers: {stats.numbers}</p>
<p>Tashkeel: {stats.tashkeel}</p>
</div>
<ArabicKeyboard
isVisible={true}
onToggle={() => {}}
callbacks={callbacks}
mode="integrated"
/>
</div>
);
}Example 2: Form Integration
'use client';
import { useState, useMemo } from 'react';
import ArabicKeyboard from '@/components/ArabicKeyboard';
import type { KeyboardCallbacks } from '@/types/keyboard.types';
export default function FormExample() {
const [currentField, setCurrentField] = useState<'name' | 'email' | 'bio' | null>(null);
const [formData, setFormData] = useState({
name: '',
email: '',
bio: '',
});
const callbacks: KeyboardCallbacks = useMemo(() => ({
onCharacterInput: (char) => {
if (!currentField) return;
setFormData(prev => ({
...prev,
[currentField]: prev[currentField] + char,
}));
},
onBackspace: () => {
if (!currentField) return;
setFormData(prev => ({
...prev,
[currentField]: prev[currentField].slice(0, -1),
}));
},
onEnter: () => {
// Auto-advance to next field
if (currentField === 'name') setCurrentField('email');
else if (currentField === 'email') setCurrentField('bio');
},
onKeyboardClose: () => {
setCurrentField(null);
},
}), [currentField]);
return (
<form>
<input
type="text"
value={formData.name}
onFocus={() => setCurrentField('name')}
placeholder="Name"
/>
<input
type="text"
value={formData.email}
onFocus={() => setCurrentField('email')}
placeholder="Email"
/>
<textarea
value={formData.bio}
onFocus={() => setCurrentField('bio')}
placeholder="Bio"
/>
<ArabicKeyboard
isVisible={currentField !== null}
onToggle={() => setCurrentField(null)}
callbacks={callbacks}
mode="integrated"
/>
</form>
);
}Example 3: Controlled Mode
'use client';
import { useState } from 'react';
import ArabicKeyboard from '@/components/ArabicKeyboard';
export default function ControlledExample() {
const [text, setText] = useState('');
const [cursor, setCursor] = useState(0);
return (
<>
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
onSelect={(e) => setCursor(e.currentTarget.selectionStart)}
/>
<ArabicKeyboard
isVisible={true}
onToggle={() => {}}
value={text}
onValueChange={setText}
cursorPosition={cursor}
onCursorPositionChange={setCursor}
mode="integrated"
/>
</>
);
}⌨️ Keyboard Layouts
Arabic Layout (KBDA1)
Standard Arabic keyboard layout with full Tashkeel support:
Row 1: 1 2 3 4 5 6 7 8 9 0 - = Backspace
Row 2: Tab ض ص ث ق ف غ ع ه خ ح ج د \
Row 3: Shift ش س ي ب ل ا ت ن م ك ط Enter
Row 4: Ctrl ئ ء ؤ ر لا ى ة و ز ظ / Shift
Row 5: Alt Space Alt
Tashkeel (Diacritics):
- Fatha (َ), Damma (ُ), Kasra (ِ)
- Sukun (ْ), Shadda (ّ), Tanween variants
- Hamza variants, Alef variants
English Layout (QWERTY)
Standard QWERTY layout with full punctuation:
Row 1: 1 2 3 4 5 6 7 8 9 0 - = Backspace
Row 2: Tab Q W E R T Y U I O P [ ] \
Row 3: Shift A S D F G H J K L ; ' Enter
Row 4: Ctrl Z X C V B N M , . / Shift
Row 5: Alt Space Alt
⚙️ Settings & Configuration
The keyboard includes comprehensive settings across 11 categories:
1. Appearance & Theme
appearance: {
theme: 'dark' | 'light' | 'high-contrast' | 'minimal' | 'colorful' | 'custom',
keyboardBackground: string, // CSS color
regularKeyColor: string,
numberKeyColor: string,
tashkeelKeyColor: string,
specialKeyColors: {
backspace: string,
enter: string,
space: string,
clear: string,
shift: string,
ctrl: string,
alt: string,
},
}2. Layout & Positioning
layout: {
position: 'bottom-center' | 'bottom-left' | 'bottom-right' |
'top-center' | 'top-left' | 'top-right' | 'floating',
width: 'full' | 'auto' | number, // px or percentage
height: 'auto' | number, // px
keySize: 'small' | 'medium' | 'large' | number,
keySpacing: 'tight' | 'normal' | 'relaxed' | number,
rowSpacing: 'tight' | 'normal' | 'relaxed' | number,
borderRadius: number, // px
padding: number, // px
}3. Behavior
behavior: {
autoCapitalize: boolean,
doubleClickDelay: number, // ms
longPressDelay: number, // ms
repeatDelay: number, // ms for key repeat
repeatInterval: number, // ms
closeOnClickOutside: boolean,
closeOnEnter: boolean,
closeOnEscape: boolean,
}4. Sound Effects
sound: {
enabled: boolean,
volume: number, // 0-100
keypress: {
enabled: boolean,
sound: 'click' | 'tap' | 'mechanical' | 'silent' | 'custom',
volume: number,
},
clear: {
enabled: boolean,
sound: string,
volume: number,
},
enter: {
enabled: boolean,
sound: string,
volume: number,
},
}5. Animations
animations: {
enabled: boolean,
slideIn: boolean,
slideOut: boolean,
duration: number, // ms
keyHoverEffect: 'none' | 'scale' | 'glow' | 'lift',
keyPressEffect: 'none' | 'ripple' | 'scale' | 'glow',
}6. Language Settings
language: {
default: 'ar' | 'en',
allowToggle: boolean,
showLanguageIndicator: boolean,
rtlDirection: boolean,
}7. Special Keys
specialKeys: {
showTashkeel: boolean,
showNumbers: boolean,
showEnglish: boolean,
showEmoji: boolean,
customKeys: Array<{
label: string,
value: string,
position: number,
}>,
}8. Accessibility
accessibility: {
ariaLabels: boolean,
keyboardNavigation: boolean,
highContrast: boolean,
screenReaderAnnouncements: boolean,
focusIndicator: boolean,
}9. Performance
performance: {
virtualScrolling: boolean,
memoization: boolean,
lazyLoadSounds: boolean,
debounceDelay: number, // ms
}10. Display
display: {
showTextArea: boolean, // Deprecated in v2.0
textAreaHeight: number,
fontSize: number,
fontFamily: string,
showClearButton: boolean,
showCloseButton: boolean,
}11. Advanced
advanced: {
enableLogging: boolean,
debugMode: boolean,
customCSS: string,
allowMultipleInstances: boolean,
}Using Settings
import { SettingsProvider, useSettings } from '@/context/SettingsContext';
function App() {
return (
<SettingsProvider initialSettings={{
appearance: { theme: 'dark' },
sound: { enabled: true, volume: 75 },
layout: { position: 'bottom-center' },
}}>
<MyKeyboardComponent />
</SettingsProvider>
);
}
function MyKeyboardComponent() {
const { settings, updateSettings } = useSettings();
return (
<ArabicKeyboard
isVisible={true}
onToggle={() => {}}
// Settings are automatically applied via context
/>
);
}🔤 TypeScript Support
Full TypeScript support with comprehensive type definitions:
import type {
ArabicKeyboardProps,
KeyboardCallbacks,
InputMetadata,
KeyboardSettings,
KeyType,
Language,
} from '@/types/keyboard.types';Key Types
type KeyType = 'letter' | 'number' | 'tashkeel' | 'special' | 'modifier';
type Language = 'ar' | 'en';
type InsertMode = 'append' | 'cursor';
type ChangeType = 'insert' | 'delete' | 'clear' | 'external';🌐 Browser Support
- ✅ Chrome 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Edge 90+
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
Requirements:
- React 18+ (React 19 recommended)
- Next.js 14+ (Next.js 15+ recommended)
- Modern browser with ES6 support
🧪 Testing
The project includes comprehensive unit tests using Jest and React Testing Library.
Running Tests
npm test # Run all tests
npm test -- --watch # Watch mode
npm test -- --coverage # With coverage reportTest Structure
Tests are organized in src/components/__tests__/:
ArabicKeyboard.test.tsx- Keyboard component testsWordDisplay.test.tsx- Floating words display testsSettings.test.tsx- Settings context and modal tests
Test Coverage
- Visibility and toggle behavior
- Keyboard key rendering (Arabic/English layouts)
- Callback integration (character input, backspace, etc.)
- Modifier keys (Shift, Ctrl, Alt)
- Settings persistence
- Accessibility
🤝 Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Run tests to ensure everything works (
npm test) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Guidelines
- Follow existing code style and patterns
- Add tests for new features
- Update documentation as needed
- Ensure all tests pass before submitting PR
- Run
npm run lintto check for linting errors
📄 License
MIT License - see LICENSE file for details
🙏 Acknowledgments
- Arabic keyboard layout based on KBDA1 standard
- Sound effects from open source libraries
- Built with Next.js, React, and TypeScript
- Styled with Tailwind CSS
📞 Support
- GitHub Issues: Report bugs or request features
- Documentation: This README and inline code comments
- Examples: See
src/components/examples/folder
🗺️ Roadmap
v2.1 (Planned)
- [ ] Swipe gesture support
- [ ] Voice input integration
- [ ] Predictive text
- [ ] Custom layouts API
v3.0 (Future)
- [ ] Multi-language support (French, Spanish, etc.)
- [ ] Emoji picker integration
- [ ] Advanced autocomplete
- [ ] Cloud sync for settings
Made with ❤️ for the Arabic-speaking developer community
