Giter Site home page Giter Site logo

alphagov / accessible-autocomplete Goto Github PK

View Code? Open in Web Editor NEW
900.0 46.0 148.0 6.08 MB

An autocomplete component, built to be accessible.

Home Page: https://alphagov.github.io/accessible-autocomplete/examples/

License: MIT License

JavaScript 96.59% CSS 3.27% Procfile 0.04% Shell 0.10%
typeahead accessibility javascript autocomplete govuk-design-system-team portfolio design-system

accessible-autocomplete's Introduction

Accessible autocomplete

The accessible autocomplete is a component that helps users choose answers from a list you provide. You can also use it to make the answers you get from users more consistent.

If you're asking users to provide their country or territory, the govuk-country-and-territory-autocomplete might be more appropriate.

npm version JavaScript Style Guide gzip size

Sauce Labs Build Status

accessible-autocomplete is a JavaScript autocomplete built from the ground up to be accessible. The design goals are:

  • Accessibility: Following WAI-ARIA best practices and testing with assistive technologies.
  • User experience: Supporting a wide variety of user needs.
  • Compatibility: Working with recommended browsers and assistive technologies.

Try out the examples!


Support

The GOV.UK Design System team maintains the accessible autocomplete as a standalone component. However, we’re only able to put in minimal work to support it.

Read about our plans to maintain this component.

Read more about the types of support we can provide.


Installation / usage

Using npm and a module system

Install it by running:

npm install --save accessible-autocomplete

The accessibleAutocomplete function will render an autocomplete <input> and its accompanying suggestions and aria-live region. Your page should provide a <label> and a container element:

<label for="my-autocomplete">Select your country</label>
<div id="my-autocomplete-container"></div>

Then import it using a module system like Browserify / Webpack / Rollup, and call the accessibleAutocomplete function, providing an array of values:

import accessibleAutocomplete from 'accessible-autocomplete'

const countries = [
  'France',
  'Germany',
  'United Kingdom'
]

accessibleAutocomplete({
  element: document.querySelector('#my-autocomplete-container'),
  id: 'my-autocomplete', // To match it to the existing <label>.
  source: countries
})

If you want to use it as a replacement for a <select> element, read the Progressive enhancement section.

As a plain JavaScript module

You can copy the dist/accessible-autocomplete.min.js file to your JavaScript folder and import it into the browser:

<script type="text/javascript" src="assets/js/accessible-autocomplete.min.js"></script>

Styling the autocomplete

A stylesheet is included with the package at dist/accessible-autocomplete.min.css.

You can copy it to your stylesheets folder and import it into the browser:

<link rel="stylesheet" href="assets/css/accessible-autocomplete.min.css" />

You can also import it using Sass:

@import "accessible-autocomplete";

Note

When styling the .autocomplete__input element, be aware that the autoselect option will render a second .autocomplete__hint input element for suggestion text. Both elements should be styled to ensure suggestions exactly align with the typed input text.

Using with Preact

If you already use Preact in your application, you can import a bundle that will use that:

import preact from 'preact'
import Autocomplete from 'accessible-autocomplete/preact'

preact.render(
  <Autocomplete id='autocomplete' source={suggest} />,
  document.querySelector('#container')
)

Try out the Preact example!

Preact versions

Preact v8.5.3 has been tested to work with the Accessible Autocomplete - although make sure to check out documented issues.

Preact 10.19.6 has been incompletely tested with the Accessible Autocomplete. No issues were found in Chrome and Firefox, but our automated tests for picking an option using the keyboard failed in Internet Explorer 11 (an issue we could not replicate when testing manually, though).

We recommend you carry out thorough testing if you wish to use this or later versions of Preact.

Using with React

If you already use React in your application, you can import a bundle that will use that:

import React from 'react'
import ReactDOM from 'react-dom'
import Autocomplete from 'accessible-autocomplete/react'

ReactDOM.render(
  <Autocomplete id='autocomplete' source={suggest} />,
  document.querySelector('#container')
)

Try out the React example!

React versions

React v15.5.4 has been tested to work with the Accessible Autocomplete - although make sure to check out documented issues.

React v15.6.2, v16.14.0, v17.0.2, and v18.2.0 have been incompletely tested with the Accessible Autocomplete. No undocumented issues were found (though be aware that React 18 dropped support for Internet Explorer)

We recommend you carry out thorough testing if you wish to use this or later versions of React.

API documentation

Required options

element

Type: HTMLElement

The container element in which the autocomplete will be rendered in.

id

Type: string

The id to assign to the autocomplete input field, to use with a <label for=id>. Not required if using enhanceSelectElement.

source

Type: Array | Function

An array of values to search when the user types in the input field, or a function to take what the user types and call a callback function with the results to be displayed.

An example of an array of values:

const countries = [
  'France',
  'Germany',
  'United Kingdom'
]

If source is a function, the arguments are: query: string, populateResults: Function

Similar to the source argument for typeahead.js, a backing data source for suggestions. query is what gets typed into the input field, which will callback to populateResults synchronously with the array of string results to display in the menu.

An example of a simple suggestion engine:

function suggest (query, populateResults) {
  const results = [
    'France',
    'Germany',
    'United Kingdom'
  ]
  const filteredResults = results.filter(result => result.indexOf(query) !== -1)
  populateResults(filteredResults)
}

Other options

inputClasses (default: null)

Type: string | null

Adds custom html classes to the generated input element.

If autoselect is set to true, the option hintClasses can be configured separately or it will default to the inputClasses value.

hintClasses (default: null)

Type: string | null

Adds custom html classes to the additional input element that appears when what the user typed matches the start of a suggestion.

If autoselect is set to true, the option inputClasses will be used as the default value unless hintClasses is set to an empty string ''.

menuAttributes (default: {})

Type: Object

Sets html attributes and their values on the generated ul menu element. Useful for adding aria-labelledby and setting to the value of the id attribute on your existing label, to provide context to an assistive technology user.

Note

To maintain assistive technology support, menu attributes id, role and onMouseLeave cannot be overridden using menuAttributes. Setting className will append to the component default and menuClasses values.

menuClasses (default: null)

Type: string | null

Adds custom html classes to the generated ul menu element.

autoselect (default: false)

Type: Boolean

Set to true to highlight the first option when the user types in something and receives results. Pressing enter will select it.

confirmOnBlur (default: true)

Type: Boolean

The autocomplete will confirm the currently selected option when the user clicks outside of the component. Set to false to disable.

cssNamespace (default: 'autocomplete')

Type: string

Use this property to override the BEM block name that the JavaScript component will use. You will need to rewrite the CSS class names to use your specified block name.

defaultValue (default: '')

Type: string

Specify a string to prefill the autocomplete with.

displayMenu (default: 'inline')

Type: 'inline' | 'overlay'

You can set this property to specify the way the menu should appear, whether inline or as an overlay.

minLength (default: 0)

Type: number

The minimum number of characters that should be entered before the autocomplete will attempt to suggest options. When the query length is under this, the aria status region will also provide helpful text to the user informing them they should type in more.

name (default: 'input-autocomplete')

Type: string

The name for the autocomplete input field, to use with a parent <form>.

onConfirm (default: () => {})

Type: Function

Arguments: confirmed: Object

This function will be called when the user confirms an option, with the option they've confirmed.

placeholder (default: '') ⚠️ not recommended ⚠️

Type: string

This option will populate the placeholder attribute on the input element.

We think placeholders have usability issues and that there are better alternatives to input placeholder text, so we do not recommend using this option.

required (default: false)

Type: Boolean

The input field will be rendered with a required attribute, see W3C required attribute definition.

showAllValues (default: false)

Type: Boolean

If this is set to true, all values are shown when the user clicks the input. This is similar to a default dropdown, so the autocomplete is rendered with a dropdown arrow to convey this behaviour.

showNoOptionsFound (default: true)

Type: Boolean

The autocomplete will display a "No results found" template when there are no results. Set to false to disable.

templates (default: undefined)

Type:

{
  inputValue: Function,
  suggestion: Function
}

This object defines templates (functions) that are used for displaying parts of the autocomplete.

inputValue is a function that receives one argument, the currently selected suggestion. It returns the string value to be inserted into the input.

suggestion is a function that receives one argument, a suggestion to be displayed. It is used when rendering suggestions, and should return a string, which can contain HTML.

⚠️ Caution: because this function allows you to output arbitrary HTML, you should make sure it's trusted, and accessible.

If your template includes child elements with defined foreground or background colours, check they display correctly in forced colors modes. For example, Windows high contrast mode.

dropdownArrow (default: A triangle pointing down)

Type: Function

A function that gets passed an object with the property className ({ className: '' }) and should return a string of HTML or a (P)React element. ⚠️ Caution: because this function allows you to output arbitrary HTML, you should make sure it's trusted, and accessible.

Internationalization

tNoResults (default: () => 'No results found')

Type: Function

A function that receives no arguments and returns the text used in the dropdown to indicate that there are no results.

tStatusQueryTooShort (default: (minQueryLength) => `Type in ${minQueryLength} or more characters for results`)

Type: Function

A function that receives one argument that indicates the minimal amount of characters needed for the dropdown to trigger and returns the text used in the accessibility hint to indicate that the query is too short.

tStatusNoResults (default: () => 'No search results')

Type: Function

A function that receives no arguments and returns the text that is used in the accessibility hint to indicate that there are no results.

tStatusSelectedOption (default: (selectedOption, length, index) => `${selectedOption} ${index + 1} of ${length} is highlighted`)

Type: Function

A function that receives three arguments - the selectedOption, the count of available options, and the (zero-based) index of the selected option - and returns the text used in the accessibility hint to indicate which option is selected.

tStatusResults

Default:

(length, contentSelectedOption) => {
  const words = {
    result: (length === 1) ? 'result' : 'results',
    is: (length === 1) ? 'is' : 'are'
  }

  return <span>{length} {words.result} {words.is} available. {contentSelectedOption}</span>
}

Type: Function

A function that receives two arguments - the count of available options and the return value of tStatusSelectedOption - and returns the text used in the accessibility hint to indicate which options are available and which is selected.

tAssistiveHint (default: () => 'When autocomplete results are available use up and down arrows to review and enter to select. Touch device users, explore by touch or with swipe gestures.')

Type: Function

A function that receives no arguments and returns the text to be assigned as the aria description of the html input element, via the aria-describedby attribute. This text is intended as an initial instruction to the assistive tech user. The aria-describedby attribute is automatically removed once user input is detected, in order to reduce screen reader verbosity.

Progressive enhancement

If your autocomplete is meant to select from a small list of options (a few hundred), we strongly suggest that you render a <select> menu on the server, and use progressive enhancement.

If you have the following HTML:

<select id="location-picker">
  <option value="fr">France</option>
  <option value="de">Germany</option>
  <option value="gb">United Kingdom</option>
</select>

You can use the accessibleAutocomplete.enhanceSelectElement function to enhance it into an autocomplete:

accessibleAutocomplete.enhanceSelectElement({
  selectElement: document.querySelector('#location-picker')
})

This will:

  • Place an autocomplete input field after the specified <select>
  • Default the autocomplete autoselect to true
  • Default the autocomplete defaultValue to the select's option[selected]
  • Default the autocomplete id to the <select>'s id
  • Default the autocomplete name attribute to '' to prevent it being included in form submissions
  • Default the autocomplete source to use existing <option>s from the <select>
  • Hide the <select> using inline display: none
  • Set the <select>'s id to ${id}-select to decouple from any <label>
  • Upon confirming a value in the autocomplete, update the original <select>

This function takes the same options as accessibleAutocomplete, with the only difference being that it uses selectElement instead of element, which needs to be an instance of HTMLSelectElement.

Note: The accessibleAutocomplete.enhanceSelectElement function is fairly light and wraps the public API for accessibleAutocomplete. If your use case doesn't fit the above defaults, try reading the source and seeing if you can write your own.

Null options

If your <select> element has a "null" option - a default option with no value - then you can pass a defaultValue option to enhanceSelectElement which will replace the label of this option when it is selected.

With the following HTML:

<select id="location-picker">
  <option value="">Select a country</option>
  <option value="fr">France</option>
  <option value="de">Germany</option>
  <option value="gb">United Kingdom</option>
</select>

Then passing a defaultValue option of '' will then leave the autocomplete blank if the null option is selected.

accessibleAutocomplete.enhanceSelectElement({
  defaultValue: '',
  selectElement: document.querySelector('#location-picker')
})

Any null options will also be filtered out of the options used to populate the source of the autocomplete element. To preserve options with no value in the autocomplete, then pass a preserveNullOptions flag of true to enhanceSelectElement.

Analytics and tracking

The following events get triggered on the input element during the life cycle of the autocomplete:

  • onConfirm - This function will be called when the user confirms an option, with the option they've chosen.

Example usage:

accessibleAutocomplete({
  // additional options
  onConfirm: (val) => {
    track(val)
  }
})

Why another autocomplete?

accessible-autocomplete was built after studying many existing solutions and prototyping patches to fix user experience or accessibility issues. It draws heavy inspiration from the following (and a lot of others):

Developing locally

Check out the CONTRIBUTING guide for instructions.

If you want to help and want to get more familiar with the codebase, try starting with the "good for beginners" issues.

License

MIT.

accessible-autocomplete's People

Contributors

36degrees avatar aliuk2012 avatar andreyyudin avatar benistary avatar colinrotherham avatar dependabot[bot] avatar domoscargin avatar dracos avatar edwardhorsford avatar ellamdav avatar eoinshaughnessy avatar ganes1410 avatar greenkeeper[bot] avatar hannalaakso avatar joelanman avatar lennym avatar lfdebrux avatar markhunter27 avatar mchughbri avatar nickcolley avatar owenatgov avatar peterjaric avatar querkmachine avatar rgarner avatar richardtowers avatar romaricpascal avatar samtsai avatar svinkle avatar tobias-g avatar tvararu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

accessible-autocomplete's Issues

Use Preact only as a production optimization

Right now the tests are a bit hairy compared with what can be done in the React world, spoke to @tvararu and we think it'd be interesting to have this project as React by default, and then allow Preact to be swapped in at prod build time.

Risks with this is we need to ensure test coverage across a React build and Preact build...

UA sniffing for iOS 10

Here's the problem:

  1. User focuses on text box
  2. On-screen keyboard shows
  3. User types some letters
  4. Suggestions display beneath text box
  5. User hides the keyboard
  6. Suggestions hide before the user had a chance to select one by tapping one of them.

#6 is the problem: when the user hides the on-screen keyboard, the blur event fires on the textbox, in iOS 10. I don't believe any other device does this including earlier versions of iOS.

I wonder if we can fix this by the approach we take to building this component.

Currently, the Javascript listens for the text box blur event and hides the suggestion list.

Here's a very early thought of mine...

Don't hide the suggestions on blur. Instead hide the suggestions when the user presses the tab key.

But what about clicking/tapping elsewhere on the page? In this case we should also hide the suggestions.

@tvararu raised concerns with listening to events that are outside of the components segment of the Document Tree.

I don't share this concern. This is the nature of developing Javascript components in the browser. It might also be that a component listens to load/scroll/resize events at the window/document/body level, for example.

As long as a component does not stop propagation/bubbling then this is, in my book, absolutely no problem.

Raising this here to open up the discussion. Critique welcomed.

Can't click on an element below the typeahead with inline menu open

(This bug would be easy to demonstrate with something like #42)

If you have a typeahead with a displayMenu: 'inline' list of options open, then when you click on a different element in the page, these events happen: mouseDown -> blur -> mouseUp.

By default, click events don't get registered until mouseUp, to allow users to change their mind and drag the cursor away before letting go of the click. However, because the blur event gets triggered before, this will collapse the typeahead menu, which will move elements beneath it in the page upwards. This "pulls the rug" underneath the mouse, and the click event won't register on the clicked element.

Support more ways of using the library

Here are a few:

Unbundled build

<script src="preact.js"></script>
<script src="lodash.debounce.js"></script>
<!-- Standalone build without all the dependencies. -->
<script src="accessible-typeahead.standalone.min.js"></script>
<script>
  AccessibleTypeahead()
</script>

JS module without all the bundled dependencies

// In package.json
{
  "dependencies": {
    "lodash.debounce": "*",
    "preact": "*",
    // ...
  }
}
// Then maybe?
import AccessibleTypeahead from 'accessible-typeahead/standalone'

AccessibleTypeahead()

Preact module

import {h} from 'preact' /** @jsx h */
import AccessibleTypeahead from 'accessible-typeahead/preact'

<AccessibleTypeahead />

React module

import React from 'react'
import AccessibleTypeahead from 'accessible-typeahead/react'

<AccessibleTypeahead />

Allow space to confirm an option

While I don't believe we've seen anyone attempt this in research, the space bar is commonly used by keyboard users to confirm things. There shouldn't be a downside to adding support for this.

Hint is selectable on some screen readers and browsers

The typeahead contains a <Hint> element that is responsible for displaying the grey text in this image:

Image of the grey typeahead hint

I've done some accessibility testing and on JAWS17 Chrome, and NVDA Chrome/FireFox/IE11, it is possible to sometimes tab to the hint input element (even though it has tabindex="-1"!), in which case the user will be told it's "read-only edit" and not be allowed to edit it. This only seems to occur when the screen readers are running.

There's a few solutions to try but one would be to simply not display the <Hint> unless it's in use.

Focus management consideration

Currently the component uses both .focus() and aria-activedescendant to announce the focused option.

According to spec a composite widget like this, should keep focus on the textbox and focus should be managed by aria-attributes (and CSS for visual highlighting), which is what I have done in my demo.

It would be good to investigate how well this works for AT.

Functionality: Down key show all results?

Not sure if this is a good idea, but when I use keyboard input on a select input, then press down on the keyboard, it'll open the select and let me go through them.

Check if element present before adding autocomplete to it

If the autocomplete code is added to a page:

  selectElement: document.querySelector('#location-picker')
})

But no #location-picker is present, it produces an error. It should do nothing if it finds the element isn't on the page.

Plan for 1.0.0

Hello,

This plugin looks really good, so is there a plan for 1.0.0?

What needs to be done to remove this ⚠️ WARNING: This project is still experimental / under development. Do not use in production. ⚠️ warning?

Thank you!

Internationalisation

Things to do:

  • Allow customisation of the aria-live region
  • Allow customisation of the "No results found" template

Possibly others.

Possible API:

AccessibleTypeahead.enhanceSelectElement({
  selectElement: document.querySelector('select'),
  lang: 'en' // Implicit default
})

AccessibleTypeahead.enhanceSelectElement({
  selectElement: document.querySelector('select'),
  lang: 'cy' // templates: AccessibleTypeahead.welshStrings
})

AccessibleTypeahead.enhanceSelectElement({
  selectElement: document.querySelector('select'),
  templates: {
    notFound: 'Nu s-a gasit'
  }
})

Possible to have two items visibly selected

It's possible to have two items visibly selected - only one should be selected at any one time.

Steps to reproduce:

  • Have a selected menu item
  • Hover down to another item and leave mouse in place
  • Use arrow keys to move selected item

Example:
location-picker-bug-multiple-selected

A possible different solution to this might be to style 'hover-selected' items differently than the 'actually-selected' items.

Feature: Update input with name of currently selected option

As users select different menu options using the arrow keys, the input should visually update with the selection. Right now it sort-of does, as the hint updates as you go down.

Here's how Baymard looks:
location-picker-update-input

Acceptance criteria:

  • Input updates to current option when using arrow keys
  • Input should update to the 'final' text - don't include extras in brackets from the typeahead.
  • No change for hover
  • If a user uses arrow keys to go back to the field, the original text should be restored
  • If a user starts typing after arrowing down, the typed text is taken as the text of the option, with the caret placed at the end.
  • With autoselect ON, when the user arrows back to the field, I'd expect the hint to be restored.

Possible to unselect all menu items when autoselect is on

When autoselect is on, an option should always be selected. This will either be the first result, or if the user has used arrow keys it may be another result. Currently using arrow keys it's possible to unselect all options.

Steps to reproduce:

  • Search for a result with autoselect on.
  • Press up arrow key

Example:
location-picker-bug-autoselect

Suggest change to success criterion 8 - number of matches

Criterion 8 currently says:
"Inform the user that N number of matches have been displayed"

I wonder if this should be:
"Inform the user when there are matches, or if there are no matches"

With another:
"(Optional) inform the user the number of matches"

I also wonder if criterion 9 should be made optional.

Reasoning: for sighted users, we don't display the number of matches - what we do indicate is whether there are matches. Is it crucial that a screen reader user is told whether there are 3 or 5 matches? or is the essential thing that they be told when there are results and when there aren't?

Use Greenkeeper 2

This project doesn't have a lot of dependencies but it would be good to use GK.

Change project name from typeahead to autocomplete

We recently decided to refer to this as an autocomplete rather than a typeahead. Autocomplete felt more natural and appears to be in more common usage (comparing similar components and search terms).

To do:

  • Change repo name
  • Change readme docs
  • Change internal references

Readability nit: Single letter variables

Issues with autoselect on iOS when meant to be disabled.

Autoselect on iOS is meant to be disabled (for accessibility reasons I think) - however it's still possible to trigger it by backspacing after picking a result.

Tested on iOS 10.3.1 with iPhone 7.

Example:
location-picker-bug-auto-select-mobile

Weirdly, for United States, the one that gets selected is not the first one:
location-picker-bug-auto-select-mobile-usae

Unicode support?

There aren't any tests that check unicode strings, so we don't know if the autocomplete works with them.

Remove unpkg from the readme

We don't recommend users to rely exclusively on unpkg in their service. They should use package managers or vendor the dependencies.

Do not set selection range on the text when confirming on iOS VoiceOver

On iOS, when you confirm an option with VoiceOver turned on, the typeahead will select the text inside the input, which will bring up the selection edit menu (copy / paste / and so on). VoiceOver will then stop telling you that you have successfully confirmed an option to tell you what's in the selection edit menu, so it just says "menu item."

Scale input relative to font-size?

At the moment the input is styled in a way that it'll only work if GOV.UK's base styles are in place, if you bump the font the input looks too small.

.typeahead__wrapper {
  position: relative;
}

.typeahead__hint,
.typeahead__input {
  -webkit-appearance: none;
  border: 2px solid;
  border-width: .125rem;
  border-radius: 0; /* Safari 10 on iOS adds implicit border rounding. */
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  margin-bottom: 0; /* BUG: Safari 10 on macOS seems to add an implicit margin. */
  width: 100%;
}

.typeahead__input {
  background-color: transparent;
  position: relative;
}

.typeahead__hint {
  color: #BFC1C3;
  position: absolute;
}

.typeahead__input:focus {
  outline-offset: 0;
  outline: 3px solid #ffbf47;
  outline-width: .1875rem;
}

.typeahead__menu {
  background-color: #fff;
  border: 2px solid #0B0C0C;
  border-width: .125rem;
  border-top: 0;
  color: #34384B;
  margin: 0;
  max-height: 342px;
  max-height: 21.375rem;
  overflow-x: hidden;
  padding: 0;
  width: 100%;
  width: calc(100% - 4px);
  width: calc(100% - .25rem);
}

.typeahead__menu--visible {
  display: block;
}

.typeahead__menu--hidden {
  display: none;
}

.typeahead__menu--overlay {
  box-shadow: rgba(0, 0, 0, 0.256863) 0 .125rem .375rem;
  left: 0;
  position: absolute;
  top: 100%;
  z-index: 100;
}

.typeahead__menu--inline {
  position: relative;
}

.typeahead__option {
  border-bottom: solid #BFC1C3;
  border-width: 1px 0;
  border-width: .0625rem 0;
  cursor: pointer;
  display: block;
  position: relative;
}

.typeahead__option:first-of-type {
  border-top-width: 0;
}

.typeahead__option:last-of-type {
  border-bottom-width: 0;
}

.typeahead__option--odd {
  background-color: #FAFAFA;
}

.typeahead__option--focused {
  background-color: #005EA5;
  border-color: #005EA5;
  color: white;
  outline: none;
}

.typeahead__option--no-results {
  background-color: #FAFAFA;
  color: #646b6f;
  cursor: not-allowed;
}

.typeahead__hint,
.typeahead__input,
.typeahead__option {
  font-size: 16px;
  font-size: 1rem;
  line-height: 1.25;
  padding: 4px;
  padding: .25rem;
}

@media (min-width: 641px) {
  .typeahead__hint,
  .typeahead__input,
  .typeahead__option {
    font-size: 19px;
    font-size: 1.1875rem;
    line-height: 1.31579;
  }
}

Support progressive enhancement of selects for users without JS

GOV.UK Verify are currently using https://github.com/JamieAppleseed/selectToAutocomplete in an alpha product. This is a jQuery plugin that takes a select tag as input and auto-magically transforms it into a typeahead.

The main advantage of this approach is that it makes the no-javascript fallback much easier to implement - you simply stamp out your select and option tags, and if the JS fails to run that's Good Enough(TM).

Of course it would still be possible to put a select in a noscript tag (or similar) to provide a no-javascript fallback while using accesible-typeahead, but the "provide a select and the plugin does the rest" is a nice workflow.

If you think that would be a nice feature I'd be happy to have a play and send you a PR. What do you think?

Autoselecting does not give clear feedback on JAWS

When using the autoselect option, when the user types in a query that brings up suggestions, the list of suggestions will update and visually highlight the first element, while offering audio feedback informing the user that it's selected. The user may press enter to confirm it.

I've tested this on JAWS17 and the typeahead does not give clear enough feedback after confirming that the user has successfully chosen the first option. Other screen reader + browser combinations accomplish this usually by simply reading out the new value; JAWS17 just says "enter," and on FireFox it also says "collapsed."

Browser JAWS17
Chrome Broken
FireFox Broken
IE11 Broken

A possible solution is to blur and refocus the input field but a bit of investigation and testing is needed to fix this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.