Near-Duplicate Input

Spots near-duplicates of existing names as you type, so a second "Marketing" tag or folder isn't created by accident.

StopsDuplicate tags with different spelling

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/near-duplicate-input.json

The files land in your project. They're yours to edit.

Usage

near-duplicate-input-usage.tsx
import { NearDuplicateInput } from "@/components/ui/near-duplicate-input"

<NearDuplicateInput
  label="New tag"
  items={tags}
  defaultValue="marketing "
  onCreate={(name) => {
    setTags((current) => [...current, name])
    setPicked(name)
  }}
  onUseExisting={setPicked}
/>

What it catches

  • Same name in different capitals or spacing
  • Punctuation differences
  • Plural vs singular (Bugs vs bug)
  • One-letter typos and swapped letters
  • Leaves different numbers alone (Q3 vs Q4)

Props

NearDuplicateInput props
PropTypeDefault
items* (required)

Names that already exist.

readonly string[]—
label

Visible label.

string"New tag"
value

Controlled text.

string—
defaultValue

Initial text when uncontrolled.

string""
onValueChange

Called with the text on every change.

(value: string) => void—
onCreate* (required)

Creates the trimmed name. Return a promise to show a pending state; throw to keep the text.

(name: string) => void | Promise<void>—
onUseExisting

Called when the user picks the existing item instead.

(item: string) => void—
messages

Warning text per reason; `{item}` marks where the existing name goes.

Partial<Record<DuplicateReason, string>>—
createLabel

Label of the create button.

string"Create"
createAnywayLabel

Create button label while a near-duplicate (but not a same-name) match is showing.

string"Create anyway"
useExistingLabel

Label of the one-tap fix that picks the existing item.

string"Use existing"

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible label; input is described by a polite hint region
  • Enter picks the existing item when a near-duplicate is shown
  • Use existing button's aria-label names the item; create shows aria-busy while pending

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Compares against the items you pass; it doesn't search your database
  • Synonyms (Sales vs Revenue) aren't detected
  • English plural rules only

What it stops

Duplicate tags with different spelling

Also known as

tags · labels · categories · create new · dedupe · folder name · tag input · taxonomy

Field type

Dependencies

Pairs well with