mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
Merge pull request #2758 from elfman/colorTag
add feature: colored tags
This commit is contained in:
68
browser/components/ColorPicker.js
Normal file
68
browser/components/ColorPicker.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { SketchPicker } from 'react-color'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './ColorPicker.styl'
|
||||
|
||||
const componentHeight = 330
|
||||
|
||||
class ColorPicker extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
color: this.props.color || '#939395'
|
||||
}
|
||||
|
||||
this.onColorChange = this.onColorChange.bind(this)
|
||||
this.handleConfirm = this.handleConfirm.bind(this)
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
this.onColorChange(nextProps.color)
|
||||
}
|
||||
|
||||
onColorChange (color) {
|
||||
this.setState({
|
||||
color
|
||||
})
|
||||
}
|
||||
|
||||
handleConfirm () {
|
||||
this.props.onConfirm(this.state.color)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { onReset, onCancel, targetRect } = this.props
|
||||
const { color } = this.state
|
||||
|
||||
const clientHeight = document.body.clientHeight
|
||||
const alignX = targetRect.right + 4
|
||||
let alignY = targetRect.top
|
||||
if (targetRect.top + componentHeight > clientHeight) {
|
||||
alignY = targetRect.bottom - componentHeight
|
||||
}
|
||||
|
||||
return (
|
||||
<div styleName='colorPicker' style={{top: `${alignY}px`, left: `${alignX}px`}}>
|
||||
<div styleName='cover' onClick={onCancel} />
|
||||
<SketchPicker color={color} onChange={this.onColorChange} />
|
||||
<div styleName='footer'>
|
||||
<button styleName='btn-reset' onClick={onReset}>Reset</button>
|
||||
<button styleName='btn-cancel' onClick={onCancel}>Cancel</button>
|
||||
<button styleName='btn-confirm' onClick={this.handleConfirm}>Confirm</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ColorPicker.propTypes = {
|
||||
color: PropTypes.string,
|
||||
targetRect: PropTypes.object,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
export default CSSModules(ColorPicker, styles)
|
||||
39
browser/components/ColorPicker.styl
Normal file
39
browser/components/ColorPicker.styl
Normal file
@@ -0,0 +1,39 @@
|
||||
.colorPicker
|
||||
position fixed
|
||||
z-index 2
|
||||
display flex
|
||||
flex-direction column
|
||||
|
||||
.cover
|
||||
position fixed
|
||||
top 0
|
||||
right 0
|
||||
bottom 0
|
||||
left 0
|
||||
|
||||
.footer
|
||||
display flex
|
||||
justify-content center
|
||||
z-index 2
|
||||
align-items center
|
||||
& > button + button
|
||||
margin-left 10px
|
||||
|
||||
.btn-cancel,
|
||||
.btn-confirm,
|
||||
.btn-reset
|
||||
vertical-align middle
|
||||
height 25px
|
||||
margin-top 2.5px
|
||||
border-radius 2px
|
||||
border none
|
||||
padding 0 5px
|
||||
background-color $default-button-background
|
||||
&:hover
|
||||
background-color $default-button-background--hover
|
||||
.btn-confirm
|
||||
background-color #1EC38B
|
||||
&:hover
|
||||
background-color darken(#1EC38B, 25%)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React from 'react'
|
||||
import { isArray } from 'lodash'
|
||||
import invertColor from 'invert-color'
|
||||
import CSSModules from 'browser/lib/CSSModules'
|
||||
import { getTodoStatus } from 'browser/lib/getTodoStatus'
|
||||
import styles from './NoteItem.styl'
|
||||
@@ -13,29 +14,38 @@ import i18n from 'browser/lib/i18n'
|
||||
/**
|
||||
* @description Tag element component.
|
||||
* @param {string} tagName
|
||||
* @param {string} color
|
||||
* @return {React.Component}
|
||||
*/
|
||||
const TagElement = ({ tagName }) => (
|
||||
<span styleName='item-bottom-tagList-item' key={tagName}>
|
||||
#{tagName}
|
||||
</span>
|
||||
)
|
||||
const TagElement = ({ tagName, color }) => {
|
||||
const style = {}
|
||||
if (color) {
|
||||
style.backgroundColor = color
|
||||
style.color = invertColor(color, { black: '#222', white: '#f1f1f1', threshold: 0.3 })
|
||||
}
|
||||
return (
|
||||
<span styleName='item-bottom-tagList-item' key={tagName} style={style}>
|
||||
#{tagName}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Tag element list component.
|
||||
* @param {Array|null} tags
|
||||
* @param {boolean} showTagsAlphabetically
|
||||
* @param {Object} coloredTags
|
||||
* @return {React.Component}
|
||||
*/
|
||||
const TagElementList = (tags, showTagsAlphabetically) => {
|
||||
const TagElementList = (tags, showTagsAlphabetically, coloredTags) => {
|
||||
if (!isArray(tags)) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (showTagsAlphabetically) {
|
||||
return _.sortBy(tags).map(tag => TagElement({ tagName: tag }))
|
||||
return _.sortBy(tags).map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
||||
} else {
|
||||
return tags.map(tag => TagElement({ tagName: tag }))
|
||||
return tags.map(tag => TagElement({ tagName: tag, color: coloredTags[tag] }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +56,7 @@ const TagElementList = (tags, showTagsAlphabetically) => {
|
||||
* @param {Function} handleNoteClick
|
||||
* @param {Function} handleNoteContextMenu
|
||||
* @param {Function} handleDragStart
|
||||
* @param {Object} coloredTags
|
||||
* @param {string} dateDisplay
|
||||
*/
|
||||
const NoteItem = ({
|
||||
@@ -59,7 +70,8 @@ const NoteItem = ({
|
||||
storageName,
|
||||
folderName,
|
||||
viewType,
|
||||
showTagsAlphabetically
|
||||
showTagsAlphabetically,
|
||||
coloredTags
|
||||
}) => (
|
||||
<div
|
||||
styleName={isActive ? 'item--active' : 'item'}
|
||||
@@ -97,7 +109,7 @@ const NoteItem = ({
|
||||
<div styleName='item-bottom'>
|
||||
<div styleName='item-bottom-tagList'>
|
||||
{note.tags.length > 0
|
||||
? TagElementList(note.tags, showTagsAlphabetically)
|
||||
? TagElementList(note.tags, showTagsAlphabetically, coloredTags)
|
||||
: <span
|
||||
style={{ fontStyle: 'italic', opacity: 0.5 }}
|
||||
styleName='item-bottom-tagList-empty'
|
||||
@@ -127,6 +139,7 @@ const NoteItem = ({
|
||||
NoteItem.propTypes = {
|
||||
isActive: PropTypes.bool.isRequired,
|
||||
dateDisplay: PropTypes.string.isRequired,
|
||||
coloredTags: PropTypes.object,
|
||||
note: PropTypes.shape({
|
||||
storage: PropTypes.string.isRequired,
|
||||
key: PropTypes.string.isRequired,
|
||||
|
||||
@@ -10,11 +10,12 @@ import CSSModules from 'browser/lib/CSSModules'
|
||||
* @param {string} name
|
||||
* @param {Function} handleClickTagListItem
|
||||
* @param {Function} handleClickNarrowToTag
|
||||
* @param {bool} isActive
|
||||
* @param {bool} isRelated
|
||||
* @param {boolean} isActive
|
||||
* @param {boolean} isRelated
|
||||
* @param {string} bgColor tab backgroundColor
|
||||
*/
|
||||
|
||||
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count}) => (
|
||||
const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, handleContextMenu, isActive, isRelated, count, color}) => (
|
||||
<div styleName='tagList-itemContainer' onContextMenu={e => handleContextMenu(e, name)}>
|
||||
{isRelated
|
||||
? <button styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} onClick={() => handleClickNarrowToTag(name)}>
|
||||
@@ -23,6 +24,7 @@ const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, hand
|
||||
: <div styleName={isActive ? 'tagList-itemNarrow-active' : 'tagList-itemNarrow'} />
|
||||
}
|
||||
<button styleName={isActive ? 'tagList-item-active' : 'tagList-item'} onClick={() => handleClickTagListItem(name)}>
|
||||
<span styleName='tagList-item-color' style={{backgroundColor: color || 'transparent'}} />
|
||||
<span styleName='tagList-item-name'>
|
||||
{`# ${name}`}
|
||||
<span styleName='tagList-item-count'>{count !== 0 ? count : ''}</span>
|
||||
@@ -33,7 +35,8 @@ const TagListItem = ({name, handleClickTagListItem, handleClickNarrowToTag, hand
|
||||
|
||||
TagListItem.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
handleClickTagListItem: PropTypes.func.isRequired
|
||||
handleClickTagListItem: PropTypes.func.isRequired,
|
||||
color: PropTypes.string
|
||||
}
|
||||
|
||||
export default CSSModules(TagListItem, styles)
|
||||
|
||||
@@ -71,6 +71,11 @@
|
||||
padding-right 15px
|
||||
font-size 13px
|
||||
|
||||
.tagList-item-color
|
||||
height 26px
|
||||
width 3px
|
||||
display inline-block
|
||||
|
||||
body[data-theme="white"]
|
||||
.tagList-item
|
||||
color $ui-inactive-text-color
|
||||
|
||||
Reference in New Issue
Block a user