DEV Community

rahul patwa
rahul patwa

Posted on

I Built a React Autocomplete Component (and Reduced it from 5MB to 35KB)

TL;DR: I built a React component for mention-based autocompletion that supports nested objects and arrays. Then I optimized it from 5MB to just 35KB. Here's the story and why you might want to use it.


The Problem: Template Hell ๐Ÿ˜ซ

Have you ever built a feature where users need to compose messages with dynamic variables?

You know, like:

  • Email templates: "Hi {{user.name}}, your order {{order.id}} is ready!"
  • Notification systems: "{{product.name}} is now {{product.price}}"
  • Chat bots: "Welcome {{user.name}} from {{user.address.city}}!"

The typical solutions are either:

  1. Manual typing - Error-prone, users don't know what's available
  2. Dropdown menus - Clunky UI, breaks the flow
  3. Custom builders - Weeks of development time

I needed something better for my project, so I built type-ahead-mention.


The Solution: Smart Autocomplete โœจ

import { MentionInput } from 'type-ahead-mention';

function EmailEditor() {
  const [template, setTemplate] = useState("Hi {{user.name}}!");

  const data = {
    user: { name: "John", email: "john@example.com" },
    order: { id: "12345", total: 99.99 }
  };

  return <MentionInput value={template} onChange={setTemplate} suggestions={data} />;
}
Enter fullscreen mode Exit fullscreen mode

Type double opening curly braces and boom - intelligent autocomplete powered by CodeMirror.

But here's where it gets interesting...


The Magic: It Handles NESTED Data ๐ŸŽฏ

Most autocomplete libraries choke on nested objects. Not this one:

const suggestions = {
  user: {
    name: "Sarah Connor",
    address: {
      city: "Los Angeles",
      street: "2144 Ventura Blvd"
    },
    roles: ["admin", "editor", "viewer"]
  }
};
Enter fullscreen mode Exit fullscreen mode

Now users can type:

  • {{user.name}} โ†’ "Sarah Connor"
  • {{user.address.city}} โ†’ "Los Angeles"
  • {{user.roles.0}} โ†’ "admin" (yes, it does arrays!)

The autocomplete guides them through the structure as they type. No docs needed.


The Plot Twist: From 5MB to 35KB ๐Ÿ“ฆ

After building v1, I published it to NPM. Package size? 5 MEGABYTES. ๐Ÿ˜ฑ

My first reaction: "That can't be right..."

But it was. Source maps + bundled dependencies = bloat city.

The Optimization Journey

Step 1: Kill the source maps

// vite.config.ts
build: {
  sourcemap: false  // Goodbye 3.9MB of .map files
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Externalize dependencies

Instead of bundling CodeMirror and friends, I made them peer dependencies:

{
  "peerDependencies": {
    "@codemirror/autocomplete": "^6.0.0",
    "@codemirror/state": "^6.0.0",
    "@uiw/react-codemirror": "^4.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

The Results ๐Ÿ“Š

Metric Before After Reduction
Compressed 1.3 MB 12 KB 99.1% โ†“
Unpacked 5.0 MB 35 KB 99.3% โ†“
ES Module 642 KB 13 KB 97.9% โ†“

Yeah, you read that right. 99% smaller.


Cool Features You'll Actually Use ๐ŸŽจ

1. Theme It Your Way

<MentionInput
  style={{
    fontSize: '16px',
    backgroundColor: '#1e1e1e',
    color: '#e0e0e0',
    borderRadius: '8px'
  }}
/>
Enter fullscreen mode Exit fullscreen mode

2. Single or Multi-line

// Single-line input
<MentionInput value={subject} onChange={setSubject} />

// Multi-line textarea
<MentionInput value={body} onChange={setBody} multiline />
Enter fullscreen mode Exit fullscreen mode

3. Template Resolution Hook

const resolved = useMentionResolver(
  "Hello {{user.name}}!", 
  { user: { name: "Alice" } }
);
// Result: "Hello Alice!"
Enter fullscreen mode Exit fullscreen mode

4. Full Keyboard Navigation

  • Arrow keys to navigate suggestions
  • Enter to select
  • Escape to dismiss
  • Tab to autocomplete

Real-World Use Cases ๐ŸŒ

1. Email Marketing Platforms
Let users create personalized emails without learning your template syntax.

2. Notification Builders
Build Slack/Discord bot message composers with dynamic fields.

3. Document Generation
Create contract templates, invoices, or reports with variable data.

4. Chat Applications
Quick replies with user context, order details, or product info.

5. Form Builders
Dynamic form field values based on user data or previous answers.


Live Demo (Try It Now!) ๐ŸŽฎ

I built an interactive demo where you can:

  • โœ… Test 5 different themes
  • โœ… Customize styles in real-time
  • โœ… Edit the JSON data structure live
  • โœ… See template resolution instantly

๐Ÿ‘‰ Play with the demo


Getting Started (2 Minutes) โšก

npm install type-ahead-mention
Enter fullscreen mode Exit fullscreen mode

Install peer dependencies:

npm install @codemirror/autocomplete @codemirror/state @codemirror/view @uiw/react-codemirror
Enter fullscreen mode Exit fullscreen mode

Basic usage:

import { MentionInput } from 'type-ahead-mention';
import { useState } from 'react';

export function App() {
  const [message, setMessage] = useState("Hi {{name}}!");
  const suggestions = { name: "World", count: 42 };

  return (
    <MentionInput 
      value={message} 
      onChange={setMessage} 
      suggestions={suggestions} 
    />
  );
}
Enter fullscreen mode Exit fullscreen mode

What I Learned ๐Ÿ“š

  1. Bundle size matters - Users will notice (and complain about) bloated packages
  2. Peer dependencies are your friend - Don't bundle what users likely already have
  3. Source maps in production? - Almost never a good idea
  4. CodeMirror is powerful - But you need to understand its extension system
  5. Interactive demos sell - Show, don't just tell

The Tech Stack ๐Ÿ› ๏ธ

  • React 18+ - Modern hooks API
  • TypeScript - Full type safety
  • CodeMirror 6 - The editor that powers VS Code's find/replace
  • Popper.js - Smart suggestion positioning
  • Vite - Lightning-fast builds

Open Questions for You ๐Ÿค”

I'd love your input on:

  1. What other autocomplete patterns do you need?

    • SQL-like syntax? Markdown helpers? Custom delimiters?
  2. Should I add a visual builder?

    • Click to insert variables vs. typing the double curly braces
  3. What about autocomplete from API calls?

    • Async suggestions, debouncing, caching?
  4. Mobile support?

    • Touch-friendly suggestion popup?

Drop your thoughts in the comments! ๐Ÿ‘‡


Try It Yourself ๐Ÿš€


The Numbers ๐Ÿ“ˆ

Since launching v2.0.1:

  • โœ… 35KB unpacked (99% smaller than v1)
  • โœ… Full TypeScript support
  • โœ… Zero runtime dependencies (except peers)
  • โœ… Works with React 18+
  • โœ… MIT licensed

What's Next? ๐Ÿ”ฎ

I'm considering:

  • Custom delimiters - Use [[var]] or $var instead of the double curly brace syntax
  • Formatting helpers - Date/number formatting filters
  • Multi-select - Pick multiple variables at once
  • Undo/redo - Built-in history management

What would YOU use most? Let me know!


Final Thoughts ๐Ÿ’ญ

Building this package taught me that optimization isn't just about performance - it's about respect for your users' bandwidth, disk space, and patience.

Going from 5MB to 35KB wasn't just a technical achievement. It was a statement: "I care about your bundle size."

If you're building any kind of template system, notification builder, or dynamic message composer, give type-ahead-mention a shot. It might save you weeks of development.

And if you find bugs or have feature requests, the repo is open! PRs welcome. ๐ŸŽ‰


Let's Connect! ๐Ÿค

  • Give it a โญ on GitHub
  • Share your use cases in the comments
  • Found a bug? Open an issue
  • Built something cool? I'd love to see it!

Question for you: What's the WORST template system you've had to work with? Share your horror stories below! ๐Ÿ‘ป


P.S. - If you're wondering why the package is called "type-ahead-mention" instead of something catchier... well, naming things is hard. ๐Ÿ˜… Got a better name? Comment below!


Last updated: November 19, 2025

Top comments (0)