Componentmedia0.77 KB gzipZero dependencies

HighlightText

Highlights query matches inside text with accent background and animated reveal

Preview

Live Preview
The quick brown fox jumps over the lazy dog

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add highlight-text

Or install the full npm package:

npm install bigbullui
import { HighlightText } from "@/components/ui/highlight-text"

<HighlightText text="The quick brown fox" query="fox" />

Usage guidance

Use HighlightText when a ticket stub surface needs Highlights query matches inside text with accent background and animated reveal Keep props minimal and prefer composition with sibling stubs.

Avoid HighlightText for long form flows or dense data grids where a dedicated layout block fits better.

Source code

highlight-text.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

import * as React from "react";
import { cn } from "./lib/utils";

export type HighlightTextProps = {
  text: string;
  query: string;
};

const highlightKeyframes = `
  @keyframes highlightIn {
    from { background-size: 0% 100%; }
    to { background-size: 100% 100%; }
  }
`;

const HighlightText = ({ text, query }: HighlightTextProps) => {
  if (!query) {
    return (
      <div
        className={cn(
          "font-mono text-sm",
          "animate-[fade-in-up_0.3s_ease-out_both]",
          "motion-reduce:animate-none"
        )}
      >
        {text}
      </div>
    );
  }

  const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const regex = new RegExp(escapedQuery, "gi");
  const parts: (string | RegExpMatchArray)[] = [];
  let lastIndex = 0;

  let match: RegExpMatchArray | null;
  while ((match = regex.exec(text)) !== null) {
    const index = match.index ?? 0;
    if (index > lastIndex) {
      parts.push(text.substring(lastIndex, index));
    }
    parts.push(match);
    lastIndex = regex.lastIndex;
  }
  if (lastIndex < text.length) {
    parts.push(text.substring(lastIndex));
  }

  return (
    <div
      className={cn(
        "font-mono text-sm relative",
        "animate-[fade-in-up_0.3s_ease-out_both]",
        "motion-reduce:animate-none"
      )}
    >
      <style>{highlightKeyframes}</style>
      {parts.map((part, i) => {
        if (typeof part === "string") {
          return (
            <span key={i} className="relative">
              {part}
            </span>
          );
        }
        const [matched] = part;

        return (
          <span
            key={i}
            className={cn(
              "bg-accent/10 text-accent-foreground rounded px-1.5",
              "animate-highlightIn 0.3s ease-out"
            )}
          >
            {matched}
          </span>
        );
      })}
    </div>
  );
};

export { HighlightText };

Props

PropTypeDescription
textstringThe text content to highlight within
querystringThe search term to highlight