Skip to main content

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’s character highlighting uses absolute positions across the entire text content. This approach simplifies highlighting compared to line-based systems, as you don’t need to calculate line numbers or offsets.

How it works

Character highlights are defined by start and end positions that count from the beginning of the text, treating the entire content as a single string. The start position is inclusive, while the end position is exclusive.
import { DyeLight, HighlightBuilder } from 'dyelight';

function Example() {
  const [text, setText] = useState('Hello world\nThis is line 2');

  // Highlight characters 0-5 ("Hello")
  const highlights = HighlightBuilder.ranges([
    { start: 0, end: 5, className: 'bg-yellow-200' },
  ]);

  return (
    <DyeLight
      value={text}
      onChange={setText}
      highlights={highlights}
    />
  );
}

Multi-line spanning

One of the key benefits of absolute positioning is that highlights automatically span across line breaks without special handling. The newline character (\n) is simply another character in the sequence.
function MultiLineExample() {
  const [text, setText] = useState('First line\nSecond line\nThird line');

  // This highlight spans from "line" in the first line to "Second" in the second line
  const highlights = HighlightBuilder.ranges([
    { start: 6, end: 18, className: 'bg-blue-200' },
  ]);

  return <DyeLight value={text} onChange={setText} highlights={highlights} />;
}
The component’s renderHighlightedLine function (from DyeLight.tsx:63) handles the complexity of splitting highlights across line boundaries internally, so you don’t need to worry about it.

Styling highlights

You can style highlights using either CSS classes or inline styles:

Using CSS classes

const highlights = HighlightBuilder.ranges([
  { start: 0, end: 5, className: 'highlight-keyword' },
]);
.highlight-keyword {
  background-color: #e3f2fd;
  color: #1976d2;
  font-weight: 600;
}

Using inline styles

const highlights = HighlightBuilder.ranges([
  {
    start: 0,
    end: 5,
    style: {
      backgroundColor: 'yellow',
      fontWeight: 'bold',
    },
  },
]);
You can combine both className and style on the same highlight. Inline styles will take precedence over class styles for any conflicting properties.

Character range types

The CharacterRange type defines the structure for highlights:
type CharacterRange = {
  start: number;          // Start position (inclusive)
  end: number;            // End position (exclusive)
  className?: string;     // CSS class name
  style?: React.CSSProperties; // Inline styles
};

Overlapping highlights

When highlights overlap, DyeLight renders them in the order they appear in the array, with later highlights taking visual precedence. The component automatically handles overlaps by clamping ranges and skipping already-highlighted portions (see DyeLight.tsx:85-119).
const highlights = [
  { start: 0, end: 10, className: 'bg-yellow-200' },
  { start: 5, end: 15, className: 'bg-blue-200' },  // Overlaps with first highlight
];
For best performance with many highlights, sort them by start position before passing them to DyeLight. The component automatically sorts ranges per line, but pre-sorting can help reduce processing time.

RTL text support

Character highlighting works seamlessly with right-to-left (RTL) text. Simply set the dir prop:
<DyeLight
  value={arabicText}
  onChange={setArabicText}
  highlights={highlights}
  dir="rtl"
/>
The component uses unicodeBidi styles (see DyeLight.tsx:12-18) to ensure highlights render correctly in both LTR and RTL contexts.

Build docs developers (and LLMs) love