Skip to content

Getting Started

Build interactive text with custom markup - quick start in minutes.

Install Markput using your preferred package manager:

Terminal window
npm install rc-marked-input

Requirements: React 17 or later.

Let’s build a marked text editor with autocomplete in three steps.

Here’s a basic editor rendering marked text. Try clicking the highlighted text:

import {MarkedInput} from 'rc-marked-input'
export const Step1Demo = () => (
<MarkedInput
Mark={({value, meta}) => <mark onClick={() => alert(meta)}>{value}</mark>}
defaultValue="Hello @[World](123)!"
/>
)

How it works:

Markput uses a special markup syntax to represent interactive elements as plain text:

  • Markup — a text pattern that encodes structured data: @[__value__](__meta__)
  • Value — the visible text shown to users (e.g., World)
  • Meta — hidden metadata for your app (e.g., 123 - user ID)
  • Mark — a React component that renders the markup visually

When Markput encounters @[World](123) in the text:

  1. Parses the markup and extracts: value="World", meta="123"
  2. Renders your Mark component with these props: <mark onClick={...}>{props.value}</mark>
  3. Preserves the original text as a simple string — easy to save or send to any backend

Since Mark is a regular React component, you can style it, add click handlers (like the onClick that shows an alert), or use any React features.

Add the options prop to enable autocomplete suggestions:

import {MarkedInput} from 'rc-marked-input'
export const Step2Demo = () => (
<MarkedInput
defaultValue="Type @ to mention someone!"
options={[
{
markup: '__value__',
slotProps: {
overlay: {
trigger: '@',
data: ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
},
},
},
]}
/>
)

How it works:

The options prop configures autocomplete behavior:

  • markup — the pattern for inserted text (__value__ inserts plain text)
  • slotProps.overlay — configuration for the built-in Suggestions component:
    • trigger — character that opens the overlay (here: @)
    • data — array of suggestions to display

When you type the trigger character @:

  1. Markput detects the trigger and shows the built-in Suggestions component
  2. As you type, suggestions are filtered based on your input
  3. When you select an item (e.g., 'Alice'), Markput inserts the text

Keyboard navigation is built-in (↑↓ to navigate, Enter to select, Esc to close).

The built-in Suggestions component is convenient, but sometimes you need full control over the UI. The Overlay prop lets you render a completely custom component, and the useOverlay hook provides all the state and actions you need.

Here’s a custom mention UI that fetches GitHub users and displays avatars:

import {MarkedInput, useOverlay} from 'rc-marked-input'
import {useState, useEffect, type RefObject} from 'react'
const User = ({avatar, login, onClick}: {avatar?: string; login?: string; onClick?: () => void}) => (
<span className={`inline-flex gap-2 ${onClick ? '!flex p-2 hover:bg-gray-100' : ''}`} onClick={onClick}>
<img src={avatar} alt="" className="rounded-full w-6 h-6" />
{login}
</span>
)
const CustomOverlay = () => {
const {select, match, style, ref} = useOverlay()
const [users, setUsers] = useState<{login: string; avatar_url: string}[]>([])
useEffect(() => {
if (!match.value) return
fetch(`https://api.github.com/search/users?q=${match.value}`)
.then(res => res.json())
.then(data => setUsers(data.items?.slice(0, 10) || []))
}, [match.value])
useEffect(() => ref.current?.showPopover(), [])
return (
<div
ref={ref as RefObject<HTMLDivElement>}
popover="auto"
style={{top: style.top, left: style.left}}
className="border border-gray-200 shadow-md"
>
{users?.map(user => (
<User
key={user.login}
avatar={user.avatar_url}
login={user.login}
onClick={() => select({value: user.login, meta: user.avatar_url})}
/>
))}
</div>
)
}
export const Step3Demo = () => (
<MarkedInput
defaultValue="Type @ to mention someone!"
Mark={({value, meta}) => <User avatar={meta} login={value} />}
Overlay={CustomOverlay}
/>
)

How it works:

The useOverlay hook returns an object with everything you need to build a custom overlay:

  • match — current search state with match.value containing what the user typed after the trigger
  • select — function to insert markup: select({value: string, meta?: string})
  • close — function to dismiss the overlay without selecting
  • style — object with top and left coordinates for positioning near the cursor
  • ref — React ref to attach to your overlay element for proper event handling

The hook handles all the complexity: detecting triggers, tracking the search query, and positioning the overlay. When you call select({value, meta}), it inserts the markup and closes the overlay.

In this example, we fetch GitHub users and store the username as value and avatar URL as meta. The Mark component then uses meta to display the avatar. You can use any UI library or custom component. Markput doesn’t impose styling constraints.

Explore these interactive examples on CodeSandbox: