Sticky categories label
parent
e108b00768
commit
21bb9eb63e
|
@ -8,7 +8,7 @@
|
|||
font-size: 16px;
|
||||
display: inline-block;
|
||||
color: #222427;
|
||||
border: 1px solid rgba(0, 0, 0, .15);
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
|||
.emoji-picker-scroll {
|
||||
overflow: scroll;
|
||||
max-height: 270px;
|
||||
padding: 6px;
|
||||
border: solid rgba(0, 0, 0, .15);
|
||||
padding: 0 6px 6px 6px;
|
||||
border: solid #d9d9d9;
|
||||
border-width: 1px 0;
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,9 @@
|
|||
display: block;
|
||||
width: 100%;
|
||||
padding: .2em .6em;
|
||||
margin-top: 6px;
|
||||
border-radius: 25px;
|
||||
border: 1px solid rgba(0, 0, 0, .15);
|
||||
border: 1px solid #d9d9d9;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
@ -48,8 +49,17 @@
|
|||
}
|
||||
|
||||
.emoji-picker-category-label {
|
||||
position: relative;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.emoji-picker-category-label span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
padding: 5px 6px;
|
||||
background-color: #fff;
|
||||
background-color: rgba(255, 255, 255, .95);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,32 +2,67 @@ import React from 'react'
|
|||
import Emoji from './emoji'
|
||||
|
||||
export default class Category extends React.Component {
|
||||
shouldComponentUpdate(props) {
|
||||
if (props.perLine != this.props.perLine) {
|
||||
return true
|
||||
componentDidMount() {
|
||||
this.container = this.refs.container
|
||||
this.label = this.refs.label
|
||||
this.parent = this.container.parentNode
|
||||
|
||||
this.margin = 0
|
||||
this.minMargin = 0
|
||||
|
||||
this.memoizeSize()
|
||||
}
|
||||
|
||||
for (let k in props.emojiProps) {
|
||||
if (props.emojiProps[k] != this.props.emojiProps[k]) {
|
||||
return true
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.memoizeSize()
|
||||
}
|
||||
|
||||
return false
|
||||
memoizeSize() {
|
||||
var { top, height } = this.container.getBoundingClientRect()
|
||||
var { top: parentTop } = this.parent.getBoundingClientRect()
|
||||
var { height: labelHeight } = this.label.getBoundingClientRect()
|
||||
|
||||
this.top = top - parentTop + this.parent.scrollTop
|
||||
this.maxMargin = height - labelHeight
|
||||
}
|
||||
|
||||
handleScroll(scrollTop) {
|
||||
var margin = scrollTop - this.top
|
||||
margin = margin < this.minMargin ? this.minMargin : margin
|
||||
margin = margin > this.maxMargin ? this.maxMargin : margin
|
||||
|
||||
if (margin == this.margin) return
|
||||
this.label.style.top = `${margin}px`
|
||||
this.margin = margin
|
||||
}
|
||||
|
||||
render() {
|
||||
var { name, emojis, perLine, emojiProps } = this.props,
|
||||
var { name, emojis, perLine, hasStickyPosition, emojiProps } = this.props,
|
||||
emojis = emojis.slice(0),
|
||||
lines = [],
|
||||
linesCount = Math.ceil(emojis.length / perLine)
|
||||
linesCount = Math.ceil(emojis.length / perLine),
|
||||
labelStyles = {},
|
||||
labelSpanStyles = {}
|
||||
|
||||
Array(linesCount).fill().forEach((_, i) =>
|
||||
lines.push(emojis.splice(0, perLine))
|
||||
)
|
||||
|
||||
return <div className='emoji-picker-category'>
|
||||
<div className='emoji-picker-category-label'>{name}</div>
|
||||
if (!hasStickyPosition) {
|
||||
labelStyles = {
|
||||
height: 28,
|
||||
}
|
||||
|
||||
labelSpanStyles = {
|
||||
position: 'absolute',
|
||||
}
|
||||
}
|
||||
|
||||
return <div ref='container' className='emoji-picker-category'>
|
||||
<div style={labelStyles} data-name={name} className='emoji-picker-category-label'>
|
||||
<span style={labelSpanStyles} ref='label'>{name}</span>
|
||||
</div>
|
||||
|
||||
{lines.map((emojis, i) =>
|
||||
<div key={`line-${i}`}>
|
||||
{emojis.map((emoji) =>
|
||||
|
@ -45,6 +80,7 @@ export default class Category extends React.Component {
|
|||
|
||||
Category.propTypes = {
|
||||
emojis: React.PropTypes.array,
|
||||
hasStickyPosition: React.PropTypes.bool,
|
||||
name: React.PropTypes.string.isRequired,
|
||||
perLine: React.PropTypes.number.isRequired,
|
||||
emojiProps: React.PropTypes.object.isRequired,
|
||||
|
@ -52,4 +88,5 @@ Category.propTypes = {
|
|||
|
||||
Category.defaultProps = {
|
||||
emojis: [],
|
||||
hasStickyPosition: true,
|
||||
}
|
||||
|
|
|
@ -5,11 +5,38 @@ import Preview from './preview'
|
|||
import Category from './category'
|
||||
|
||||
export default class Picker extends React.Component {
|
||||
componentWillMount() {
|
||||
var stickyTestElement = document.createElement('div')
|
||||
for (let prefix of ['', '-webkit-', '-ms-', '-moz-', '-o-']) {
|
||||
stickyTestElement.style.position = `${prefix}sticky`
|
||||
}
|
||||
|
||||
this.hasStickyPosition = !!stickyTestElement.style.position.length
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.handleScroll()
|
||||
}
|
||||
|
||||
handleEmojiOver(emoji) {
|
||||
var { preview } = this.refs
|
||||
preview.setState({ emoji: emoji })
|
||||
}
|
||||
|
||||
handleScroll() {
|
||||
var target = this.refs.scroll,
|
||||
scrollTop = target.scrollTop
|
||||
|
||||
if (!this.hasStickyPosition) {
|
||||
Array(data.categories.length).fill().forEach((_, i) => {
|
||||
var category = this.refs[`category-${i}`]
|
||||
if (category) {
|
||||
category.handleScroll(scrollTop)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var { perLine, emojiSize, sheetURL } = this.props
|
||||
|
||||
|
@ -18,20 +45,22 @@ export default class Picker extends React.Component {
|
|||
Categories
|
||||
</div>
|
||||
|
||||
<div ref="scroll" className='emoji-picker-scroll'>
|
||||
<div ref="scroll" className='emoji-picker-scroll' onScroll={this.handleScroll.bind(this)}>
|
||||
<input
|
||||
type='text'
|
||||
placeholder='Search'
|
||||
className='emoji-picker-search'
|
||||
/>
|
||||
|
||||
{data.categories.map((category) => {
|
||||
{data.categories.map((category, i) => {
|
||||
if (category.name == 'Skins') return null
|
||||
return <Category
|
||||
ref={`category-${i}`}
|
||||
key={category.name}
|
||||
name={category.name}
|
||||
emojis={category.emojis}
|
||||
perLine={perLine}
|
||||
hasStickyPosition={this.hasStickyPosition}
|
||||
emojiProps={{
|
||||
size: emojiSize,
|
||||
sheetURL: sheetURL,
|
||||
|
|
Loading…
Reference in New Issue