React自动完成组件 - react-autocompletely

2017-07-25      1558      JavaScript
项目简介

react-autocompletely

Primitives to build simple, flexible, WAI-ARIA compliant React autocomplete components

The problem

You need an autocomplete experience in your application and you want it to be accessible. You also want it to be simple and flexible to account for your use cases.

This solution

This is a collection of primitive components that you can compose together to create an autocomplete component which you can reuse in your application. It's based on ideas from the talk "Compound Components" which effectively gives you maximum flexibility with a minimal API because you are responsible for the rendering of the autocomplete components.

This differs from other solutions which render things for their use case and then expose many options to allow for extensibility causing an API that is less easy to use and less flexible as well as making the implementation more complicated and harder to contribute to.

Installation

This component is currently under development and is not yet released...

This module is distributed via npm which is bundled with node and should be installed as one of your project'sdependencies:

npm install --save react-autocompletely

This package also depends onreactandprop-types. Please make sure you have those installed as well.

Usage

Things are still in flux a little bit (looking for feedback).

import Autocomplete from 'react-autocompletely'

function BasicAutocomplete({items, onChange}) {
  return (
    <Autocomplete onChange={onChange}>
      <Autocomplete.Input placeholder="Favorite color ?" />
      <Autocomplete.Controller>
        {({isOpen, value, selectedItem, highlightedIndex}) =>
          isOpen &&
          <div style={{border: '1px solid #ccc'}}>
            {items
              .filter(
                i =>
                  !value ||
                  i.toLowerCase().includes(value.toLowerCase()),
              )
              .map((item, index) =>
                (<Autocomplete.Item
                  value={item}
                  index={index}
                  key={item}
                  highlightedIndex={highlightedIndex}
                  selectedItem={selectedItem}
                >
                  {item}
                </Autocomplete.Item>),
              )}
          </div>
        }
      </Autocomplete.Controller>
    </Autocomplete>
  )
}

function App() {
  return (
    <BasicAutocomplete
      items={['apple', 'orange', 'carrot']}
      onChange={item => console.log(item)}
    />
  )
}

Available components and relevant props:

Autocomplete

This is the main component. It renders adivand forwards props. Wrap everything in this.

getValue

function(item: any)| defaults to an identity function (i => String(i))

Used to determine thevaluefor the selected item.

defaultHighlightedIndex

number/null| defaults tonull

This is the initial index to highlight when the autocomplete first opens.

getA11yStatusMessage

function({ resultCount, highlightedItem, getValue})| default messages provided in English

This function is passed as props to aStatuscomponent nested within and allows you to create your own assertive ARIA statuses.

A defaultgetA11yStatusMessagefunction is provided that will checkresultCountand return "No results." or if there are results but no item is highlighted, "resultCountresults are available, use up and down arrow keys to navigate." If an item is highlighted it will rungetValue(highlightedItem)and display the value of thehighlightedItem.

onChange

function(item: any)| required

Called when the user selects an item

component

string/Component| defaults to'div'

This allows you to controll what is rendered as the root element.

innerRef

function(node)| optional

If you want to get a reference to thedivrendered byAutocomplete, you can use this like you would arefprop.

Autocomplete.Input

This is the input component. It renders aninputand forwards props.

defaultValue

string/null| defaults to null

The initial value the input should have when it's mounted.

Autocomplete.Controller

This component allows you to receive and interact with the state of the autocomplete component.

children

function({})| required

This is called with an object with the properties listed below:

property type description
highlightedIndex number/null the currently highlighted item
setHighlightedIndex function(index: number) call to set a new highlighted index
value string/null the current value of the autocomplete
isOpen boolean the menu open state
toggleMenu function(state: boolean) toggle the menu open state (ifstateis not provided, then it will be set to the inverse of the current state)
openMenu function() opens the menu
closeMenu function() closes the menu
selectedItem any the currently selected item
clearSelection function() clears the selection
selectItem function(item: any) selects the given item
selectItemAtIndex function(index: number) selects the item at the given index
selectHighlightedItem function() selects the item that is currently highlighted

Autocomplete.Button

This component renders abuttontag and allows you to toggle theMenucomponent. You can definitely build something like this yourself (all of the available APIs are exposed to you via theController), but this is nice because it will also apply all of the proper ARIA attributes.

Autocomplete.Item

Render your items inside this component. This renders adivand forwards all props.

index

number| required

this is howreact-autocompletelykeeps track of your item when updating thehighlightedIndexas the user keys around.

value

any| required

This is the item data that will be selected when the user selects a particular item.

Examples

Examples exist on codesandbox.io :

If you would like to add an example, follow these steps:

  1. Fork this codesandbox
  2. Update the code for your example (add some form of documentation to explain what it is)
  3. Update the title and description
  4. Add the tag:react-autocompletely:example

Inspiration

I was heavily inspired by Ryan Florence and his talk entitled: "Compound Components" . I also took a few ideas from the code in react-autocomplete and jQuery UI's Autocomplete .

You can watch me build the first iteration ofreact-autocompletelyon YouTube:

Other Solutions

You can implement these other solutions usingreact-autocompletely, but if you'd prefer to use these out of the box solutions, then that's fine too:

Contributors

Thanks goes to these people ( emoji key ):

Kent C. Dodds

�� �� �� ⚠️

Jack Moore

��

Travis Arnold

�� ��

Jeremy Gayed

��

Haroen Viaene

��

monssef

��

Federico Zivolo

��