` element.
- The `Item` component gives you huge flexibility to format and style listbox items however you like. They can be as rich as required, containing images, icons, multiple fields, etc.
- The `Item` component receives the following props when rendered:
- **`appearsInDefaultListbox`** (boolean) If `true` indicates that the item appears in the default listbox rather than the listbox. This allows default listbox items to be styled completely differently to listbox items if required.
- **`groupId`** (string) The `id` of the group supplied in the `listbox` or `defaultListbox` prop.
- **`groupIndex`** (number) The index of the group. Matches the order supplied in the `listbox` or `defaultListbox` prop. Zero-indexed.
- **`groupName`** (string) The `name` of the group supplied in the `listbox` or `defaultListbox` prop.
- **`index`** (number) The index of the item within the listbox. Zero-indexed. This allows you to style, say, the first item differently to all the rest in the listbox.
- **`isHighlighted`** (boolean) If `true` indicates that the item is currently in a highlighted state
- **`item`** The item in the same format as supplied by the `listbox` or `defaultListbox` prop.
- **`query`** The text currently entered in the search box. This can be used to show matched text in the item.
- **`searchType`** (string) Either `"startswith"` or `"contains"`. Indicates how the item was matched to the query.
- **`setSelected`** (function) If executed, sets the selected item to whatever is passed to the function. This allows sub-items to be displayed within an item. For example, you may wish to provide selectable neighbourhoods or attractions within a city item. The function receives two arguments:
1. `value` (object / array / string) The value of the item to select
1. `displayField` (string / number / undefined) The key or index of the field inside `value` that represents the text to display in the search box once selected. If the `value` argument is a string, this must be set to `undefined`.
- **`totalItems`** The total number of items currently displayed inside the listbox.
### `GroupName`
- Type: React component
- Default: `undefined`
- If supplied, this component is rendered within the group heading `
` element.
- By default the group name is simply a text string. This component allows you to supply custom styling, for example adding an icon.
- The `GroupName` component receives the following props when rendered:
- **`children`** (string) The `name` of the group supplied in the `listbox` or `defaultListbox` prop.
- **`id`** (string) The `id` of the group supplied in the `listbox` or `defaultListbox` prop.
- **`index`** (number) The index of the group. Matches the order supplied in the `listbox` or `defaultListbox` prop. Zero-indexed.
```
--------------------------------
### Configure Default Listbox with Dynamic Function
Source: https://github.com/tomsouthall/turnstone/blob/main/README.md
Allows for dynamic generation of default listbox content using a function. This function receives a query and must return a promise that resolves to an array of group objects, similar to the array data structure. This is ideal for complex data sources or when results need to be structured on the fly.
```jsx
(query) => fetch(`/api/default-locations`).then(res => res.json()).then(locations => { const {recentSearches, popularCities} = locations; return [ { name: 'Recent Searches', displayField: 'name', data: recentSearches, id: 'recent', ratio: 1 }, { name: 'Popular Cities', displayField: 'name', data: popularCities, id: 'popular', ratio: 1 } ] })
```
--------------------------------
### Turnstone Component Props
Source: https://github.com/tomsouthall/turnstone/blob/main/README.md
Configuration options for the Turnstone component, including item highlighting, matching text display, and search behavior.
```APIDOC
## Component Props
### `highlightedItem`
Note that `item` and `highlightedItem` are mutually exclusive. An item `
` has the `highlightedItem` styling applied when it is highlighted either via a `mouseover` event or via use of the up and down arrow keys.
### `match`
The `` element that wraps any item text that matches the text entered into the search box. A common approach is to invert the styling so that the matched text is at a normal font weight and the remaining text is displayed in bold.
### `tabIndex`
- Type: `number`
- Default: `undefined`
- The HTML `tabindex` attribute applied to the search box.
### `text`
- Type: `string`
- Default: `undefined`
- Text appearing in the search box when first rendered
- Will cause `onSelect` to fire automatically if there is a matching result
### `typeahead`
- Type: `string`
- Default: `true`
- If `true` shows typeahead text as the user enters text into the search box. This matches the currently highlighted item in the listbox, so long as the item starts with the search box text.
```
--------------------------------
### Turnstone Component Props
Source: https://github.com/tomsouthall/turnstone/blob/main/README.md
This section details the available props for the Turnstone component, explaining their types, default values, and functionality.
```APIDOC
## Turnstone Component Props
### `autoFocus`
- Type: `boolean`
- Default: `false`
- If `true` the search input automatically receives focus
- Note: If `defaultListbox` prop is supplied, setting `autoFocus` to true causes the default listbox to be automatically opened.
### `cancelButton`
- Type: `boolean`
- Default: `false`
- If `true` a cancel button is rendered. The cancel button is displayed only when the search box receives focus. It is particularly useful for mobile screen sizes where a "back" button is required
in order to exit the focused state of the search box.
### `cancelButtonAriaLabel`
- Type: `string`
- Default: `"Cancel"`
- The value of the `aria-label` attribute on the cancel button element.
### `clearButton`
- Type: `boolean`
- Default: `false`
- If `true` a clear button is rendered whenever the user has entered at least one character into the search box.
- Clicking the clear button has the same effect as pressing the Esc key while entering text into the search box. The contents of the searchbox are cleared and focus is retained.
- Suggested styling for the clear button is to position it absolutely overlaying the right of the search box, for example:
```css
.clearButton {
display: block;
width: 2rem;
right: 0px;
top: 0px;
bottom: 0px;
position: absolute;
color: #a8a8a8;
cursor: pointer;
border: none;
background: transparent;
padding:0;
}
```
### `clearButtonAriaLabel`
- Type: `string`
- Default: `"Clear contents"`
- The value of the `aria-label` attribute on the clear button element.
### `debounceWait`
- Type: `number`
- Default: `250`
- The wait time in milliseconds after the user finishes typing before the search query is sent to the fetch function.
- This reduces the number of API calls made by the fetch function
- Set to `0` if you want no wait at all (e.g. if your listbox data is not fetched asynchronously)
```
--------------------------------
### Configure Default Listbox with Array Data
Source: https://github.com/tomsouthall/turnstone/blob/main/README.md
Defines the default listbox content using an array of objects, where each object represents a group of items. This is useful for displaying multiple categorized lists, such as recent searches and popular locations. Data can be provided directly or fetched asynchronously.
```jsx
[{ name: 'Recent Searches', displayField: 'name', data: () => Promise.resolve(JSON.parse(localStorage.getItem('recent')) || []), id: 'recent', ratio: 1 }, { name: 'Popular Cities', displayField: 'name', data: [ { name: 'Paris, France', coords: '48.86425, 2.29416' }, { name: 'Rome, Italy', coords: '41.89205, 12.49209' }, { name: 'Orlando, Florida, United States', coords: '28.53781, -81.38592' }, { name: 'London, England', coords: '51.50420, -0.12426' }, { name: 'Barcelona, Spain', coords: '41.40629, 2.17555' }, { name: 'New Orleans, Louisiana, United States', coords: '29.95465,-90.07507' }, { name: 'Chicago, Illinois, United States', coords: '41.85003,-87.65005' }, { name: 'Manchester, England', coords: '53.48095,-2.23743' } ], id: 'popular', ratio: 1 }]
```
--------------------------------
### Styled Turnstone with Grouped API Results in React
Source: https://github.com/tomsouthall/turnstone/blob/main/README.md
Illustrates a styled Turnstone component fetching and displaying grouped search results from two different API sources (cities and airports). It includes configuration for debouncing, maximum items, and custom styling.
```jsx
import React, { useState } from 'react'
import Turnstone from 'turnstone'
const styles = {
input,
inputFocus,
query,
typeahead,
cancelButton,
clearButton,
listbox,
groupHeading,
item,
highlightedItem
}
const maxItems = 10
const listbox = [
{
id: 'cities',
name: 'Cities',
ratio: 8,
displayField: 'name',
data: (query) =>
fetch(`/api/cities?q=${encodeURIComponent(query)}&limit=${maxItems}`)
.then(response => response.json()),
searchType: 'startswith'
},
{
id: 'airports',
name: 'Airports',
ratio: 2,
displayField: 'name',
data: (query) =>
fetch(`/api/airports?q=${encodeURIComponent(query)}&limit=${maxItems}`)
.then(response => response.json()),
searchType: 'contains'
}
]
export default function Example() {
return (
)
}
```