Skip to content

Demos

Default autocomplete

<Autocomplete data={topMovies} label="Label" />

Autocomplete with numbers

<Autocomplete
  inputValue="201"
  showClearButton
  label="Label"
  data={numbersData}
  searchNumbers={true}
/>

Autocomplete with a custom title

  • keepValue means the input value gets not removed after an input blur happens.
  • showClearButton means a clear button will show up when the input field contains a value.
<Autocomplete
  data={topMovies}
  keepValue={true}
  showClearButton={true}
  label="Label"
  placeholder="Custom placeholder ..."
  onChange={({ data }) => {
    console.log('onChange', data)
  }}
/>

Async usage, dynamically update data during typing

This example simulates server delay with a timeout and - if it gets debounced, we cancel the timeout. Read more about the debounce method.

Also, you may consider using disableFilter if you have a backend doing the search operation.

const onTypeHandler = ({
  value,
  showIndicator,
  hideIndicator,
  updateData,
  showNoOptionsItem,
  debounce,
  /* ... */
}) => {
  console.log('typed value:', value)
  showIndicator()
  debounce(
    ({ value }) => {
      console.log('debounced value:', value)
      const normalizedValue = value.trim().toLowerCase()
      const filteredData = topMovies.filter(({ content }) => {
        if (typeof content === 'string') {
          return content.toLowerCase().includes(normalizedValue)
        }
        if (Array.isArray(content)) {
          return content
            .filter((part) => typeof part === 'string')
            .join(' ')
            .toLowerCase()
            .includes(normalizedValue)
        }
        return false
      })
      const newData = normalizedValue.length > 0 ? filteredData : topMovies

      // simulate server delay
      const timeout = setTimeout(() => {
        // update the drawerList
        updateData(newData)
        hideIndicator()
        if (newData.length === 0) {
          showNoOptionsItem()
        }
      }, 600)

      // cancel invocation method
      return () => clearTimeout(timeout)
    },
    {
      value,
    },
    250
  )
}
render(
  <Autocomplete
    mode="async"
    onType={onTypeHandler}
    noScrollAnimation={true}
    placeholder="Search ..."
  />
)

Update data dynamically on the first focus

const onFocusHandler = ({ updateData, dataList, showIndicatorItem }) => {
  if (!dataList.length) {
    showIndicatorItem()
    setTimeout(() => {
      updateData(topMovies)
    }, 1e3)
  }
}
render(
  <Autocomplete
    mode="async"
    noScrollAnimation={true}
    preventSelection={true}
    onType={({ value /* updateData, ... */ }) => {
      console.log('onType', value)
    }}
    onFocus={onFocusHandler}
  />
)

With a Button to toggle the open / close state

NB: Just to show the possibility; the data is given as a function.

<Autocomplete
  label="Label"
  value={10}
  showSubmitButton={true}
  onChange={({ data }) => {
    console.log('onChange', data)
  }}
>
  {() => topMovies}
</Autocomplete>

With a predefined input/search value

<Autocomplete
  label="Label"
  inputValue="the pa ther"
  noAnimation
  onChange={({ data }) => {
    console.log('onChange', data)
  }}
>
  {() => topMovies}
</Autocomplete>

Inline results

Use the inline property to render the results list persistently open in normal document flow, instead of as an overlay. The toggle button is hidden, while filtering, highlighting, selection and keyboard navigation stay the same.

  • The Shawshank Redemption
  • The GodfatherLine with more info
  • The Godfather: Part IIAnchor 1Anchor 2Line with more info
  • The Dark Knight
  • 12 Angry MenSecond rowThird row
  • Schindler's List
  • Pulp Fiction
  • The Lord of the Rings: The Return of the King
  • The Good, the Bad and the Ugly
  • Fight Club
  • The Lord of the Rings: The Fellowship of the Ring
  • Star Wars: Episode V - The Empire Strikes Back
  • Forrest Gump
  • Inception
  • The Lord of the Rings: The Two Towers
  • One Flew Over the Cuckoo's Nest
  • Goodfellas
  • The Matrix
  • Seven Samurai
  • Star Wars: Episode IV - A New Hope
  • City of God
  • Se7en
  • The Silence of the Lambs
  • It's a Wonderful Life
  • Life Is Beautiful
  • The Usual Suspects
  • Léon: The Professional
  • Spirited Away
  • Saving Private Ryan
  • Once Upon a Time in the West
  • American History X
  • Interstellar
  • Casablanca
  • City Lights
  • Psycho
  • The Green Mile
  • The Intouchables
  • Modern Times
  • Raiders of the Lost Ark
  • Rear Window
  • The Pianist
  • The Departed
  • Terminator 2: Judgment Day
  • Back to the Future
  • Whiplash
  • Gladiator
  • Memento
  • The Prestige
  • The Lion King
  • Apocalypse Now
  • Alien
  • Sunset Boulevard
  • Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb
  • The Great Dictator
  • Cinema Paradiso
  • The Lives of Others
  • Grave of the Fireflies
  • Paths of Glory
  • Django Unchained
  • The Shining
  • WALL·E
  • American Beauty
  • The Dark Knight Rises
  • Princess Mononoke
  • Aliens
  • Oldboy
  • Once Upon a Time in America
  • Witness for the Prosecution
  • Das Boot
  • Citizen Kane
  • North by Northwest
  • Vertigo
  • Star Wars: Episode VI - Return of the Jedi
  • Reservoir Dogs
  • Braveheart
  • M
  • Requiem for a Dream
  • Amélie
  • A Clockwork Orange
  • Like Stars on Earth
  • Taxi Driver
  • Lawrence of Arabia
  • Double Indemnity
  • Eternal Sunshine of the Spotless Mind
  • Amadeus
  • To Kill a Mockingbird
  • Toy Story 3
  • Logan
  • Full Metal Jacket
  • Dangal
  • The Sting
  • 2001: A Space Odyssey
  • Singin' in the Rain
  • Toy Story
  • Bicycle Thieves
  • The Kid
  • Inglourious Basterds
  • Snatch
  • 3 Idiots
  • Monty Python and the Holy Grail
<Autocomplete inline stretch label="Label" data={topMovies} />

Different sizes

Four sizes are available: small, default, medium and large.

<Flex.Vertical>
  <Autocomplete label="Label" size="default" data={() => topMovies} />
  <Autocomplete label="Label" size="medium" data={() => topMovies} />
  <Autocomplete label="Label" size="large" data={() => topMovies} />
</Flex.Vertical>

Data suffix value

Data is provided as such:

const { locale } = React.useContext(Context)
const data = [
{
suffixValue: (
<NumberFormat.Currency srLabel="Total:" locale={locale}>
{12345678}
</NumberFormat.Currency>
),
selectedValue: `Brukskonto (${ban})`,
content: ['Brukskonto', ban],
},
]
12 345 678,00 kr
const CustomWidth = styled(Autocomplete)`
  .dnb-drawer-list__root,
  .dnb-autocomplete__shell {
    width: 50vw;
    min-width: 15rem;
    max-width: 30rem;
  }
`
render(
  <CustomWidth
    value={1}
    data={numbers}
    size="medium"
    icon={null}
    showSubmitButton
    label="From account"
  />
)

Custom width

const CustomWidthOne = styled(Autocomplete)`
  .dnb-autocomplete__shell {
    width: 10rem;
  }
`
const CustomWidthTwo = styled(Autocomplete)`
  &.dnb-autocomplete--is-popup .dnb-drawer-list__root {
    width: 12rem;
  }
`
const CustomWidthThree = styled(Autocomplete)`
  /** Change the "__shell" width */
  .dnb-autocomplete__shell {
    width: 12rem;
  }

  /** Change the "__list" width */
  .dnb-drawer-list__root {
    width: 20rem;
  }
`
render(
  <Flex.Vertical>
    <CustomWidthOne
      label="Label"
      labelSrOnly
      size="default"
      iconPosition="left"
      data={topMovies}
    />
    <CustomWidthTwo
      label="Label"
      labelSrOnly
      size="medium"
      data={topMovies}
    />
    <CustomWidthThree
      label="Label"
      labelSrOnly
      size="large"
      align="right"
      iconPosition="right"
      icon="bell"
      data={topMovies}
    />
  </Flex.Vertical>
)

Autocomplete with status message

You need to select a movie
<Autocomplete
  data={topMovies}
  label="Label"
  status="You need to select a movie"
  statusState="information"
  showSubmitButton
/>

Autocomplete with List item content

Reuse the List row layout for rich option content. The option is already an <li> and wraps its content in <span> elements, so use element="span" on List.Item.Basic and its cells to keep the markup valid. Give the Autocomplete a width that fits both the title and the end value. Provide selectedValue with the plain text so the input shows a sensible value once an option is selected, and searchContent so typing still filters the options. See rendering a row outside a List.Container for the details.

// A List row keeps its end cell at content width, so the row needs
// horizontal room. Give the Autocomplete a width of its own, or the
// title column will be squeezed by the end cell.
const AccountAutocomplete = styled(Autocomplete)`
  .dnb-autocomplete__shell,
  .dnb-drawer-list__root {
    width: 22rem;
  }
`
const data = [
  {
    selectedKey: 'accounts',
    // selectedValue is the plain text shown in the input once selected;
    // searchContent keeps typing/filtering working with rich content
    selectedValue: 'Accounts',
    searchContent: 'Accounts Bills Savings',
    content: (
      <List.Item.Basic element="span">
        <List.Cell.Title element="span">Accounts</List.Cell.Title>
        <List.Cell.End element="span">Bills, Savings</List.Cell.End>
      </List.Item.Basic>
    ),
  },
  {
    selectedKey: 'loans',
    selectedValue: 'Loans',
    searchContent: 'Loans Mortgage Car',
    content: (
      <List.Item.Basic element="span">
        <List.Cell.Title element="span">Loans</List.Cell.Title>
        <List.Cell.End element="span">Mortgage, Car</List.Cell.End>
      </List.Item.Basic>
    ),
  },
  {
    selectedKey: 'cards',
    selectedValue: 'Cards',
    searchContent: 'Cards Visa Mastercard',
    content: (
      <List.Item.Basic element="span">
        <List.Cell.Title element="span">Cards</List.Cell.Title>
        <List.Cell.End element="span">Visa, Mastercard</List.Cell.End>
      </List.Item.Basic>
    ),
  },
]
render(<AccountAutocomplete data={data} label="Label" />)

Groups

If an item has a groupIndex property, it will use the groups in the groups property. Only the first group can be without title, all other groups must have a title.

<Autocomplete
  groups={[undefined, 'Pets', 'Cars']}
  data={[
    {
      groupIndex: 0,
      content: 'Default 1',
    },
    {
      groupIndex: 0,
      content: 'Default 2',
    },
    {
      groupIndex: 1,
      content: 'Cat',
    },
    {
      groupIndex: 1,
      content: 'Dog',
    },
    {
      groupIndex: 2,
      content: 'Jeep',
    },
    {
      groupIndex: 2,
      content: 'Van',
    },
  ]}
/>

No divider

We can remove the divider between items with the noDivider prop. Beware that this can make information dense lists difficult to parse.

<Autocomplete
  noDivider
  data={['Cat', 'Dog', 'Canary', 'Hamster', 'Piglet']}
/>
Edit on GitHub