Not Found Component for emoji search
If a user's search returns no results, the sleuth_or_spy emoji appears. We would instead like for a custom image to appear. We propose creating a NotFound component that uses the the sleuth_or_spy emoji on default when a user's search returns no results but otherwise uses what the user passes throughrelease
parent
b1c499fc8d
commit
8e6d363d8b
12
README.md
12
README.md
|
@ -50,6 +50,7 @@ import { Picker } from 'emoji-mart'
|
||||||
| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
|
| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
|
||||||
| **style** | | | Inline styles applied to the root element. Useful for positioning |
|
| **style** | | | Inline styles applied to the root element. Useful for positioning |
|
||||||
| **title** | | `Emoji Mart™` | The title shown when no emojis are hovered |
|
| **title** | | `Emoji Mart™` | The title shown when no emojis are hovered |
|
||||||
|
| **notFound** | | `{notFoundImg = ''}` | [Not Found](#not-found) |
|
||||||
|
|
||||||
#### I18n
|
#### I18n
|
||||||
```js
|
```js
|
||||||
|
@ -234,6 +235,17 @@ const customEmojis = [
|
||||||
<Picker custom={customEmojis} />
|
<Picker custom={customEmojis} />
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Not Found
|
||||||
|
You can provide a custom Not Found object which will allow the appearance of the not found search results to change. In this case, we change the default 'sleuth_or_spy' emoji to Octocat when our search finds no results.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Picker } from 'emoji-mart'
|
||||||
|
|
||||||
|
const notFound = () => <img src='https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7' />
|
||||||
|
|
||||||
|
<Picker notFound={notFound} />
|
||||||
|
```
|
||||||
|
|
||||||
## Headless search
|
## Headless search
|
||||||
The `Picker` doesn’t have to be mounted for you to take advantage of the advanced search results.
|
The `Picker` doesn’t have to be mounted for you to take advantage of the advanced search results.
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,12 @@
|
||||||
padding-top: 70px;
|
padding-top: 70px;
|
||||||
color: #858585;
|
color: #858585;
|
||||||
}
|
}
|
||||||
|
.emoji-mart-no-results-img {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
.emoji-mart-no-results .emoji-mart-category-label {
|
.emoji-mart-no-results .emoji-mart-category-label {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import frequently from '../utils/frequently'
|
import frequently from '../utils/frequently'
|
||||||
import { getData } from '../utils'
|
import { getData } from '../utils'
|
||||||
import { NimbleEmoji } from '.'
|
import { NimbleEmoji, NotFound } from '.'
|
||||||
|
|
||||||
export default class Category extends React.Component {
|
export default class Category extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -144,7 +144,14 @@ export default class Category extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
var { id, name, hasStickyPosition, emojiProps, i18n } = this.props,
|
var {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
hasStickyPosition,
|
||||||
|
emojiProps,
|
||||||
|
i18n,
|
||||||
|
notFound,
|
||||||
|
} = this.props,
|
||||||
emojis = this.getEmojis(),
|
emojis = this.getEmojis(),
|
||||||
labelStyles = {},
|
labelStyles = {},
|
||||||
labelSpanStyles = {},
|
labelSpanStyles = {},
|
||||||
|
@ -191,21 +198,12 @@ export default class Category extends React.Component {
|
||||||
|
|
||||||
{emojis &&
|
{emojis &&
|
||||||
!emojis.length && (
|
!emojis.length && (
|
||||||
<div>
|
<NotFound
|
||||||
<div>
|
i18n={i18n}
|
||||||
{NimbleEmoji({
|
notFound={notFound}
|
||||||
data: this.data,
|
data={this.data}
|
||||||
...emojiProps,
|
emojiProps={emojiProps}
|
||||||
size: 38,
|
/>
|
||||||
emoji: 'sleuth_or_spy',
|
|
||||||
onOver: null,
|
|
||||||
onLeave: null,
|
|
||||||
onClick: null,
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="emoji-mart-no-results-label">{i18n.notfound}</div>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -220,6 +218,7 @@ Category.propTypes = {
|
||||||
perLine: PropTypes.number.isRequired,
|
perLine: PropTypes.number.isRequired,
|
||||||
emojiProps: PropTypes.object.isRequired,
|
emojiProps: PropTypes.object.isRequired,
|
||||||
recent: PropTypes.arrayOf(PropTypes.string),
|
recent: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
notFound: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
Category.defaultProps = {
|
Category.defaultProps = {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export { default as Anchors } from './anchors'
|
export { default as Anchors } from './anchors'
|
||||||
export { default as Category } from './category'
|
export { default as Category } from './category'
|
||||||
export { default as Preview } from './preview'
|
export { default as Preview } from './preview'
|
||||||
|
export { default as NotFound } from './not-found'
|
||||||
export { default as Search } from './search'
|
export { default as Search } from './search'
|
||||||
export { default as Skins } from './skins'
|
export { default as Skins } from './skins'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { NimbleEmoji } from '.'
|
||||||
|
|
||||||
|
export default class NotFound extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
const { data, emojiProps, i18n, notFound } = this.props
|
||||||
|
|
||||||
|
const imageComponent = (notFound && notFound()) || (
|
||||||
|
<div>
|
||||||
|
{NimbleEmoji({
|
||||||
|
data: data,
|
||||||
|
...emojiProps,
|
||||||
|
size: 38,
|
||||||
|
emoji: 'sleuth_or_spy',
|
||||||
|
onOver: null,
|
||||||
|
onLeave: null,
|
||||||
|
onClick: null,
|
||||||
|
})}
|
||||||
|
<div className="emoji-mart-no-results-label">{i18n.notfound}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return <div className="emoji-mart-no-results">{imageComponent}</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotFound.propTypes = {
|
||||||
|
notFound: PropTypes.func.isRequired,
|
||||||
|
emojiProps: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
NotFound.defaultProps = {
|
||||||
|
notFound: () => {},
|
||||||
|
}
|
|
@ -467,6 +467,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
exclude,
|
exclude,
|
||||||
recent,
|
recent,
|
||||||
autoFocus,
|
autoFocus,
|
||||||
|
notFound,
|
||||||
} = this.props,
|
} = this.props,
|
||||||
{ skin } = this.state,
|
{ skin } = this.state,
|
||||||
width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
width = perLine * (emojiSize + 12) + 12 + 2 + measureScrollbar()
|
||||||
|
@ -539,6 +540,7 @@ export default class NimblePicker extends React.PureComponent {
|
||||||
onLeave: this.handleEmojiLeave,
|
onLeave: this.handleEmojiLeave,
|
||||||
onClick: this.handleEmojiClick,
|
onClick: this.handleEmojiClick,
|
||||||
}}
|
}}
|
||||||
|
notFound={notFound}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -71,6 +71,7 @@ const PickerPropTypes = {
|
||||||
imageUrl: PropTypes.string.isRequired,
|
imageUrl: PropTypes.string.isRequired,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
notFound: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
const PickerDefaultProps = {
|
const PickerDefaultProps = {
|
||||||
|
@ -96,6 +97,7 @@ const PickerDefaultProps = {
|
||||||
emojiTooltip: EmojiDefaultProps.tooltip,
|
emojiTooltip: EmojiDefaultProps.tooltip,
|
||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
custom: [],
|
custom: [],
|
||||||
|
notFound: () => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -41,7 +41,19 @@ storiesOf('Picker', module)
|
||||||
showPreview={boolean('Show preview', true)}
|
showPreview={boolean('Show preview', true)}
|
||||||
showSkinTones={boolean('Show skin tones', true)}
|
showSkinTones={boolean('Show skin tones', true)}
|
||||||
custom={CUSTOM_EMOJIS}
|
custom={CUSTOM_EMOJIS}
|
||||||
/>
|
/>))
|
||||||
|
.add('with a custom not found image', () => (
|
||||||
|
<Picker
|
||||||
|
notFound={
|
||||||
|
() => <img src='https://assets-cdn.github.com/images/icons/emoji/octocat.png?v7' />
|
||||||
|
}
|
||||||
|
/>))
|
||||||
|
.add('with a custom not found SVG', () => (
|
||||||
|
<Picker
|
||||||
|
notFound={
|
||||||
|
() => <svg aria-labelledby="simpleicons-jira-icon" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title id="simpleicons-jira-icon">Jira icon</title><path d="M23.323 11.33L13.001 1 12 0 4.225 7.775.67 11.33a.96.96 0 0 0 0 1.347l7.103 7.103L12 24l7.771-7.771.121-.121 3.431-3.431a.945.945 0 0 0 0-1.347zM12 15.551L8.449 12 12 8.453 15.548 12 12 15.551z"/></svg>
|
||||||
|
}
|
||||||
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
storiesOf('Emoji', module)
|
storiesOf('Emoji', module)
|
||||||
|
|
Loading…
Reference in New Issue