Skip to content

Commit

Permalink
Update renderSuggestionsContainer signature to include query
Browse files Browse the repository at this point in the history
* Changed the focusFirstSuggestion prop to be highlightFirstSuggestion
* inputProps.onBlur gets highlightedSuggestion now instead of
focusedSuggestion
* theme.suggestionFocused changed to theme.suggestionHighlighted
* Added the following keys to theme:
  - suggestionsContainerOpen
  - inputOpen
  - inputFocused
  - suggestionFirst
  - sectionContainerFirst
  • Loading branch information
moroshko committed Feb 26, 2017
1 parent 8a9845a commit b8de1d4
Show file tree
Hide file tree
Showing 26 changed files with 558 additions and 348 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ module.exports = {
'react/no-unused-prop-types': 0, // https://github.com/yannickcr/eslint-plugin-react/issues/944
'react/prefer-es6-class': [2, 'always'],
'react/prefer-stateless-function': 2,
'react/prop-types': 2,
'react/prop-types': [2, { skipUndeclared: true }],
'react/react-in-jsx-scope': 2,
'react/require-optimization': 0,
'react/require-render-return': 2,
Expand Down
7 changes: 5 additions & 2 deletions FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ When the suggestions container has a scroll bar, and you scroll beyond the start
```js
import IsolatedScroll from 'react-isolated-scroll';

function renderSuggestionsContainer({ ref, ...rest }) {
function renderSuggestionsContainer({ containerProps, children }) {
const { ref, ...restContainerProps } = containerProps;
const callRef = isolatedScroll => {
if (isolatedScroll !== null) {
ref(isolatedScroll.component);
}
};

return (
<IsolatedScroll {...rest} ref={callRef} />
<IsolatedScroll ref={callRef} {...restContainerProps}>
{children}
</IsolatedScroll>
);
}

Expand Down
76 changes: 44 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ Check out the [Homepage](http://react-autosuggest.js.org) and the [Codepen examp
* Full control over [suggestions rendering](#renderSuggestionProp)
* Suggestions can be presented as [plain list](http://codepen.io/moroshko/pen/LGNJMy) or [multiple sections](http://codepen.io/moroshko/pen/qbRNjV)
* Suggestions can be retrieved [asynchronously](http://codepen.io/moroshko/pen/EPZpev)
* [Focus the first suggestion](#focusFirstSuggestionProp) in the list if you wish
* Supports styling using [CSS Modules](https://github.com/css-modules/css-modules), [Radium](https://github.com/FormidableLabs/radium), [Inline styles](https://facebook.github.io/react/docs/dom-elements.html#style), global CSS, [and more](#themeProp)
* [Highlight the first suggestion](#highlightFirstSuggestionProp) in the list if you wish
* Supports styling using [CSS Modules](https://github.com/css-modules/css-modules), [Radium](https://github.com/FormidableLabs/radium), [Aphrodite](https://github.com/Khan/aphrodite), [JSS](https://github.com/cssinjs/jss), [and more](#themeProp)
* You decide [when to show suggestions](#shouldRenderSuggestionsProp) (e.g. when user types 2 or more characters)
* [Always render suggestions](#alwaysRenderSuggestionsProp) (useful for mobile and modals)
* [Pass through arbitrary props to the input element](#inputPropsProp) (e.g. placeholder, type, [onChange](#inputPropsOnChange), [onBlur](#inputPropsOnBlur), or any other), or [take full control on the rendering of the input](#renderInputComponentProp) (useful for integration with other libraries)
Expand Down Expand Up @@ -152,7 +152,7 @@ class Example extends React.Component {
| [`onSuggestionSelected`](#onSuggestionSelectedProp) | Function | | Will be called every time suggestion is selected via mouse or keyboard. |
| [`shouldRenderSuggestions`](#shouldRenderSuggestionsProp) | Function | | When the input element is focused, Autosuggest will consult this function when to render suggestions. Use it, for example, if you want to display suggestions when input value is at least 2 characters long. |
| [`alwaysRenderSuggestions`](#alwaysRenderSuggestionsProp) | Boolean | | Set it to `true` if you'd like to render suggestions even when the input element is not focused. |
| [`focusFirstSuggestion`](#focusFirstSuggestionProp) | Boolean | | Set it to `true` if you'd like Autosuggest to automatically highlight the first suggestion. |
| [`highlightFirstSuggestion`](#highlightFirstSuggestionProp) | Boolean | | Set it to `true` if you'd like Autosuggest to automatically highlight the first suggestion. |
| [`focusInputOnSuggestionClick`](#focusInputOnSuggestionClickProp) | Boolean | | Set it to `false` if you don't want Autosuggest to keep the input element focused when suggestions are clicked/tapped. |
| [`multiSection`](#multiSectionProp) | Boolean | | Set it to `true` if you'd like to display suggestions in multiple sections (with optional titles). |
| [`renderSectionTitle`](#renderSectionTitleProp) | Function | ✓<br>when `multiSection={true}` | Use your imagination to define how section titles are rendered. |
Expand Down Expand Up @@ -330,12 +330,12 @@ where:
The signature is:

```js
function onBlur(event, { focusedSuggestion })
function onBlur(event, { highlightedSuggestion })
```

where:

* `focusedSuggestion` - the suggestion that was highlighted just before the input element lost focus, or `null` if there was no highlighted suggestion.
* `highlightedSuggestion` - the suggestion that was highlighted just before the input element lost focus, or `null` if there was no highlighted suggestion.

<a name="onSuggestionSelectedProp"></a>
#### onSuggestionSelected (optional)
Expand Down Expand Up @@ -388,10 +388,10 @@ this.state = {
};
```

<a name="focusFirstSuggestionProp"></a>
#### focusFirstSuggestion (optional)
<a name="highlightFirstSuggestionProp"></a>
#### highlightFirstSuggestion (optional)

When `focusFirstSuggestion={true}`, Autosuggest will automatically highlight the first suggestion. Defaults to `false`.
When `highlightFirstSuggestion={true}`, Autosuggest will automatically highlight the first suggestion. Defaults to `false`.

<a name="focusInputOnSuggestionClickProp"></a>
#### focusInputOnSuggestionClick (optional)
Expand Down Expand Up @@ -474,47 +474,54 @@ const renderInputComponent = inputProps => (
<a name="renderSuggestionsContainerProp"></a>
#### renderSuggestionsContainer (optional)

You shouldn't specify `renderSuggestionsContainer` unless you want to customize the content or behaviour of the suggestions container beyond rendering the suggestions themselves. For example, you might want to add a custom text before/after the suggestions list, or [customize the scrolling behaviour of the suggestions container](https://github.com/moroshko/react-autosuggest/blob/master/FAQ.md#limitSuggestionsContainerScrolling).
You shouldn't specify `renderSuggestionsContainer` unless you want to customize the content or behaviour of the suggestions container beyond rendering the suggestions themselves. For example, you might want to add a custom text before/after the suggestions list, or to [customize the scrolling behaviour of the suggestions container](https://github.com/moroshko/react-autosuggest/blob/master/FAQ.md#limitSuggestionsContainerScrolling).

The signature is:

```js
function renderSuggestionsContainer(props)
function renderSuggestionsContainer({ containerProps, children, query })
```

You should pass all the `props` to the topmost element that is returned from `renderSuggestionsContainer` with the following exceptions:
where:

* `children` - these are the suggestions themselves. It's up to you where to render them.
* `ref` - when `renderSuggestionsContainer` returns a composite component (e.g. `<IsolatedScroll ... />` as opposed to a DOM node like `<div ... />`), you should call `ref` with the topmost element that the composite component renders.
* `containerProps` - props that you MUST pass to the topmost element that is returned from `renderSuggestionsContainer`.
* `children` - the suggestions themselves. It's up to you where to render them.
* `query` - Same as `query` in [`renderSuggestion`](#renderSuggestionProp).

Example:
For example:

```js
function renderSuggestionsContainer({ children, ...rest }) {
function renderSuggestionsContainer({ containerProps , children, query }) {
return (
<div {...rest}>
<p>
Some text
</p>
<div {... containerProps}>
{children}
<div>
Press Enter to search <strong>{query}</strong>
</div>
</div>
);
}
```

When `renderSuggestionsContainer` returns a composite component (e.g. `<IsolatedScroll ... />` as opposed to a DOM node like `<div ... />`), you MUST call `containerProps.ref` with the topmost element that the composite component renders.

For example:

```js
import IsolatedScroll from 'react-isolated-scroll';

function renderSuggestionsContainer({ ref, ...rest }) {
function renderSuggestionsContainer({ containerProps, children }) {
const { ref, ...restContainerProps } = containerProps;
const callRef = isolatedScroll => {
if (isolatedScroll !== null) {
ref(isolatedScroll.component);
}
};

return (
<IsolatedScroll {...rest} ref={callRef} />
<IsolatedScroll ref={callRef} {...restContainerProps}>
{children}
</IsolatedScroll>
);
}
```
Expand All @@ -524,7 +531,7 @@ function renderSuggestionsContainer({ ref, ...rest }) {

Autosuggest comes with no styles.

It uses [react-themeable](https://github.com/markdalgleish/react-themeable) to allow you to style your Autosuggest component using [CSS Modules](https://github.com/css-modules/css-modules), [Radium](https://github.com/FormidableLabs/radium), [React Style](https://github.com/js-next/react-style), [JSS](https://github.com/jsstyles/jss), [Inline styles](https://facebook.github.io/react/docs/dom-elements.html#style), or even global CSS.
It uses [react-themeable](https://github.com/markdalgleish/react-themeable) that allows you to style your Autosuggest component using [CSS Modules](https://github.com/css-modules/css-modules), [Radium](https://github.com/FormidableLabs/radium), [Aphrodite](https://github.com/Khan/aphrodite), [JSS](https://github.com/cssinjs/jss), [Inline styles](https://facebook.github.io/react/docs/dom-elements.html#style), and global CSS.

For example, to style the Autosuggest using CSS Modules, do:

Expand All @@ -535,7 +542,7 @@ For example, to style the Autosuggest using CSS Modules, do:
.input { ... }
.suggestionsContainer { ... }
.suggestion { ... }
.suggestionFocused { ... }
.suggestionHighlighted { ... }
...
```

Expand All @@ -550,15 +557,20 @@ When not specified, `theme` defaults to:

```js
{
container: 'react-autosuggest__container',
containerOpen: 'react-autosuggest__container--open',
input: 'react-autosuggest__input',
suggestionsContainer: 'react-autosuggest__suggestions-container',
suggestionsList: 'react-autosuggest__suggestions-list',
suggestion: 'react-autosuggest__suggestion',
suggestionFocused: 'react-autosuggest__suggestion--focused',
sectionContainer: 'react-autosuggest__section-container',
sectionTitle: 'react-autosuggest__section-title'
container: 'react-autosuggest__container',
containerOpen: 'react-autosuggest__container--open',
input: 'react-autosuggest__input',
inputOpen: 'react-autosuggest__input--open',
inputFocused: 'react-autosuggest__input--focused',
suggestionsContainer: 'react-autosuggest__suggestions-container',
suggestionsContainerOpen: 'react-autosuggest__suggestions-container--open',
suggestionsList: 'react-autosuggest__suggestions-list',
suggestion: 'react-autosuggest__suggestion',
suggestionFirst: 'react-autosuggest__suggestion--first',
suggestionHighlighted: 'react-autosuggest__suggestion--highlighted',
sectionContainer: 'react-autosuggest__section-container',
sectionContainerFirst: 'react-autosuggest__section-container--first',
sectionTitle: 'react-autosuggest__section-title'
}
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
-webkit-appearance: none;
}

.react-autosuggest__input:focus {
.react-autosuggest__input--focused {
outline: none;
}

.react-autosuggest__input::-ms-clear {
display: none;
}

.react-autosuggest__container--open .react-autosuggest__input {
.react-autosuggest__input--open {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
Expand All @@ -31,7 +31,7 @@
display: none;
}

.react-autosuggest__container--open .react-autosuggest__suggestions-container {
.react-autosuggest__suggestions-container--open {
display: block;
position: absolute;
top: 51px;
Expand All @@ -57,17 +57,20 @@
padding: 10px 20px;
}

.react-autosuggest__suggestion--focused {
.react-autosuggest__suggestion--highlighted {
background-color: #ddd;
}

.react-autosuggest__section-title {
padding: 10px 0 0 10px;
font-size: 12px;
color: #777;
.react-autosuggest__section-container {
border-top: 1px dashed #ccc;
}

.react-autosuggest__section-container:first-child .react-autosuggest__section-title {
.react-autosuggest__section-container--first {
border-top: 0;
}

.react-autosuggest__section-title {
padding: 10px 0 0 10px;
font-size: 12px;
color: #777;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,37 @@
border-radius: @border-radius;
-webkit-appearance: none;

&:focus {
outline: none;
}

&::-ms-clear {
display: none;
}
}

.containerOpen & {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.inputOpen {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}

.inputFocused {
outline: none;
}

.suggestionsContainer {
display: none;
}

.containerOpen & {
display: block;
position: absolute;
top: 51px;
width: 280px;
border: 1px solid @border-color;
background-color: #fff;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
font-size: 20px;
border-bottom-left-radius: @border-radius;
border-bottom-right-radius: @border-radius;
z-index: 2;
}
.suggestionsContainerOpen {
display: block;
position: absolute;
top: 51px;
width: 280px;
border: 1px solid @border-color;
background-color: #fff;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
font-size: 20px;
border-bottom-left-radius: @border-radius;
border-bottom-right-radius: @border-radius;
z-index: 2;
}

.suggestionsList {
Expand All @@ -59,13 +59,14 @@
cursor: pointer;
padding: 10px 20px;
height: 48px;
border-top: 1px solid #ddd;
}

&:not(:first-child) {
border-top: 1px solid #ddd;
}
.suggestionFirst {
border-top: 0;
}

.suggestionFocused {
.suggestionHighlighted {
background-color: #0C7EAF;
color: #fff;
}
Expand Down Expand Up @@ -101,7 +102,7 @@
color: #ee0000;
font-weight: 400;

.suggestionFocused & {
.suggestionHighlighted & {
color: #120000;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export default class MultipleSections extends Component {
</div>
<div className={styles.description}>
Suggestions can also be presented in multiple sections.
Note that we focus the first suggestion by default here.
Note that we highlight the first suggestion by default here.
</div>
<Link
className={styles.codepenLink}
Expand All @@ -106,7 +106,7 @@ export default class MultipleSections extends Component {
renderSectionTitle={renderSectionTitle}
getSectionSuggestions={getSectionSuggestions}
inputProps={inputProps}
focusFirstSuggestion={true}
highlightFirstSuggestion={true}
focusInputOnSuggestionClick={focusInputOnSuggestionClick}
theme={theme}
id="multiple-sections-example"
Expand Down
Loading

0 comments on commit b8de1d4

Please sign in to comment.