Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ragaeeb/dyelight/llms.txt
Use this file to discover all available pages before exploring further.
DyeLight provides full support for right-to-left (RTL) text rendering, making it suitable for Arabic, Hebrew, Persian, and other RTL languages.
Using the dir prop
Set the text direction using the dir prop:
import { DyeLight } from 'dyelight';
function RTLEditor() {
const [text, setText] = useState('مرحبا بالعالم');
return (
<DyeLight
value={text}
onChange={setText}
dir="rtl" // Enable right-to-left rendering
className="font-arabic text-lg"
/>
);
}
Direction options
| Value | Description |
|---|
"ltr" | Left-to-right (default) - for English, Spanish, etc. |
"rtl" | Right-to-left - for Arabic, Hebrew, Persian, etc. |
How RTL rendering works
When dir="rtl" is set, DyeLight automatically:
- Applies direction to both layers - The textarea and highlight overlay both receive
dir="rtl"
- Adjusts scrollbar compensation - Scrollbars appear on the left side in RTL mode
- Preserves text flow - Unicode bidirectional algorithm is respected
The highlight synchronization system (in src/hooks/useHighlightSync.ts) automatically adjusts padding based on text direction:
const isRTL = computedStyle.direction === 'rtl';
if (scrollbarWidth > 0) {
if (isRTL) {
// Add padding to left side for RTL scrollbar
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
highlightLayer.style.paddingLeft = `${paddingLeft + scrollbarWidth}px`;
} else {
// Add padding to right side for LTR scrollbar
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
highlightLayer.style.paddingRight = `${paddingRight + scrollbarWidth}px`;
}
}
This ensures the highlight overlay stays pixel-perfect aligned with the textarea text, even when scrollbars appear.
Scrollbar compensation happens automatically - you don’t need to handle it manually.
Bidirectional text handling
DyeLight preserves the browser’s native bidirectional text algorithm through careful CSS styling:
Line-level bidi inheritance
Each line wrapper inherits the bidirectional context:
const BIDI_LINE_STYLE: React.CSSProperties = {
unicodeBidi: 'inherit',
};
This allows the line to respect the overall dir setting.
Span-level bidi normalization
Highlight spans use normal bidirectional behavior:
const BIDI_SPAN_STYLE: React.CSSProperties = {
unicodeBidi: 'normal',
};
This ensures that highlighted portions don’t break the text flow.
These styles are automatically applied - you don’t need to configure them.
RTL examples
Arabic text with highlighting
import { useState } from 'react';
import { DyeLight, HighlightBuilder } from 'dyelight';
function ArabicEditor() {
const [text, setText] = useState('مرحبا بالعالم\nهذا مثال للنص العربي');
// Highlight the word "مرحبا" (Hello)
const highlights = HighlightBuilder.words(
text,
['مرحبا'],
'bg-yellow-200'
);
return (
<DyeLight
value={text}
onChange={setText}
dir="rtl"
highlights={highlights}
className="font-arabic text-lg p-4"
rows={6}
/>
);
}
Hebrew text with pattern matching
import { useState } from 'react';
import { DyeLight, HighlightBuilder } from 'dyelight';
function HebrewEditor() {
const [text, setText] = useState('שלום עולם\nזה דוגמה לטקסט עברי');
// Highlight Hebrew words using regex
const highlights = HighlightBuilder.pattern(
text,
/[\u0590-\u05FF]+/g, // Hebrew Unicode range
'text-blue-600 font-semibold'
);
return (
<DyeLight
value={text}
onChange={setText}
dir="rtl"
highlights={highlights}
className="font-hebrew p-4"
/>
);
}
Mixed bidirectional text
DyeLight handles mixed LTR/RTL content correctly:
function MixedTextEditor() {
const [text, setText] = useState(
'English text مع نص عربي and back to English'
);
return (
<DyeLight
value={text}
onChange={setText}
dir="ltr" // Primary direction
className="p-4"
/>
);
}
The browser’s Unicode bidirectional algorithm automatically handles embedded RTL/LTR segments within the text.
Styling RTL text
When styling RTL text, consider:
Font selection
Use appropriate fonts for your target language:
<DyeLight
value={arabicText}
onChange={setArabicText}
dir="rtl"
className="font-['Noto_Nastaliq_Urdu'] text-lg"
/>
Text alignment
Text automatically aligns to the right in RTL mode. You can override with CSS:
<DyeLight
value={text}
onChange={setText}
dir="rtl"
className="text-center" // Center alignment
/>
Container styling
Apply RTL-aware spacing:
<DyeLight
value={text}
onChange={setText}
dir="rtl"
containerClassName="pr-4 pl-2" // Right padding larger (start of text)
className="p-4"
/>
Implementation details
The RTL implementation is in src/DyeLight.tsx:
export const getHighlightLayerStyle = (
dir: React.CSSProperties['direction'],
textareaHeight?: number,
): React.CSSProperties => ({
...DEFAULT_HIGHLIGHT_LAYER_STYLE,
direction: dir, // Apply direction to overlay
height: textareaHeight ? `${textareaHeight}px` : undefined,
});
Both the textarea and overlay receive the same dir attribute:
<div dir={dir} ref={highlightLayerRef} style={highlightLayerStyle}>
{highlightedContent}
</div>
<textarea
dir={dir}
// ... other props
/>
This ensures perfect synchronization between the two layers.
Browser support
RTL support works in all modern browsers:
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
Older browsers may have inconsistent bidirectional text rendering. Test thoroughly if you need to support legacy browsers.