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