
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
react-token-autocomplete
Advanced tools
A style-agnostic token/tag autocomplete component for React. Ships with zero default styles — bring your own CSS, Tailwind, CSS modules, or any styling solution.
npm install react-token-autocomplete
Requires React 18 or 19 as a peer dependency.
import { TokenAutocomplete } from 'react-token-autocomplete'
function App() {
return (
<TokenAutocomplete
options={['React', 'Vue', 'Svelte', 'Angular', 'Solid']}
placeholder="Add a framework..."
onAdd={(value) => console.log('Added:', value)}
onRemove={(value) => console.log('Removed:', value)}
/>
)
}
Every element exposes a className prop — no style overrides or CSS specificity battles:
<TokenAutocomplete
options={['React', 'Vue', 'Svelte']}
className="flex flex-wrap items-center gap-1 border rounded-lg p-2 focus-within:ring-2 focus-within:ring-blue-500"
inputClassName="outline-none flex-1 min-w-[120px] bg-transparent"
tokenClassName="inline-flex items-center gap-1 bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full text-sm"
tokenRemoveClassName="hover:text-red-600 cursor-pointer text-blue-400"
optionsClassName="absolute z-10 mt-1 w-full bg-white border rounded-lg shadow-lg max-h-60 overflow-auto"
optionClassName="px-3 py-2 cursor-pointer hover:bg-gray-50"
optionSelectedClassName="bg-blue-50"
placeholderClassName="text-gray-400"
processingClassName="animate-spin h-4 w-4 border-2 border-blue-500 border-t-transparent rounded-full"
/>
| Prop | Type | Default | Description |
|---|---|---|---|
value | string[] | — | Controlled value (see Controlled Mode) |
onChange | (values: string[]) => void | — | Called with full values array on every add/remove |
options | string[] | [] | Available options to select from |
defaultValues | string[] | [] | Initial selected tokens (uncontrolled mode only) |
placeholder | string | '' | Placeholder text when empty |
threshold | number | 0 | Min characters before showing suggestions |
processing | boolean | false | Show a loading indicator |
autoFocus | boolean | false | Focus input on mount |
filterOptions | boolean | true | Filter options by input text |
simulateSelect | boolean | false | Single-value select mode (hides input after selection) |
limitToOptions | boolean | false | Only allow values from options (no custom input) |
parseOption | (option: string) => ReactNode | — | Custom render for dropdown options |
parseToken | (token: string) => ReactNode | — | Custom render for tokens |
parseCustom | (value: string) => string | — | Transform custom input values |
onInputChange | (value: string) => void | — | Called when input text changes |
onAdd | (value: string) => void | — | Called when a token is added |
onRemove | (value: string, index: number) => void | — | Called when a token is removed |
| Prop | Element |
|---|---|
className | Outer container <div> |
inputClassName | Text <input> |
tokenClassName | Token <span> |
tokenRemoveClassName | Token remove <button> |
optionsClassName | Dropdown <ul> |
optionClassName | Each option <li> |
optionSelectedClassName | Currently highlighted option (added alongside optionClassName) |
placeholderClassName | Placeholder <span> |
processingClassName | Loading indicator <span> |
| Key | Action |
|---|---|
Enter | Add the currently highlighted option |
Escape | Close the dropdown |
Backspace | Remove last token (when input is empty) |
ArrowUp / ArrowDown | Navigate options |
The component supports both uncontrolled (defaultValues) and controlled (value + onChange) modes. Controlled mode works seamlessly with form libraries like react-hook-form.
import { useState } from 'react'
import { TokenAutocomplete } from 'react-token-autocomplete'
function App() {
const [tags, setTags] = useState<string[]>([])
return (
<TokenAutocomplete
options={['React', 'Vue', 'Svelte']}
value={tags}
onChange={setTags}
/>
)
}
The component forwards a ref to its internal <input> element, so react-hook-form's Controller can manage focus automatically.
import { useForm, Controller } from 'react-hook-form'
import { TokenAutocomplete } from 'react-token-autocomplete'
interface FormData {
tags: string[]
}
function TagForm() {
const { control, handleSubmit } = useForm<FormData>({
defaultValues: { tags: [] },
})
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<Controller
name="tags"
control={control}
rules={{ validate: (v) => v.length > 0 || 'At least one tag required' }}
render={({ field }) => (
<TokenAutocomplete
ref={field.ref}
value={field.value}
onChange={field.onChange}
options={['React', 'Vue', 'Svelte', 'Angular', 'Solid']}
placeholder="Add tags..."
limitToOptions
/>
)}
/>
<button type="submit">Submit</button>
</form>
)
}
Note:
onAddandonRemovestill fire alongsideonChange, so you can use them for analytics or side effects without interfering with form state.
For full control over rendering, use the useTokenAutocomplete hook:
import { useTokenAutocomplete } from 'react-token-autocomplete'
function CustomAutocomplete() {
const {
values,
inputValue,
availableOptions,
showOptions,
setInputValue,
addValue,
removeValue,
handleKeyDown,
handleOptionMouseEnter,
handleOptionSelect,
inputRef,
containerRef,
focus,
selectedIndex,
} = useTokenAutocomplete({
options: ['React', 'Vue', 'Svelte'],
onAdd: (v) => console.log('added', v),
})
return (
<div ref={containerRef} onClick={focus}>
{values.map((v, i) => (
<span key={i}>
{v}
<button onClick={() => removeValue(i)}>×</button>
</span>
))}
<input
ref={inputRef}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
onFocus={focus}
/>
{showOptions && (
<ul>
{availableOptions.map((opt, i) => (
<li
key={opt}
onClick={() => handleOptionSelect(opt)}
onMouseEnter={() => handleOptionMouseEnter(opt)}
style={{ background: i === selectedIndex ? '#eee' : undefined }}
>
{opt}
</li>
))}
</ul>
)}
</div>
)
}
// Components
import { TokenAutocomplete, Token, Options, Option } from 'react-token-autocomplete'
// Headless hook
import { useTokenAutocomplete } from 'react-token-autocomplete'
// Types
import type {
TokenAutocompleteProps,
TokenProps,
OptionsProps,
OptionProps,
UseTokenAutocompleteOptions,
UseTokenAutocompleteReturn,
} from 'react-token-autocomplete'
npm install # install dependencies
npm run dev # run examples playground
npm run build # build library (ESM + CJS + types)
npm test # run unit tests
npm run test:watch # run unit tests in watch mode
npm run e2e # run Playwright e2e tests (mobile, tablet, desktop)
npm run lint # type-check with tsc
ISC
FAQs
A style-agnostic token/tag autocomplete component for React
We found that react-token-autocomplete demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.