1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-13 09:46:22 +00:00

update NoteDetail design

This commit is contained in:
Dick Choi
2016-10-14 04:00:59 +09:00
parent 8f0789bc6d
commit fdd0c84441
14 changed files with 392 additions and 194 deletions

View File

@@ -140,20 +140,6 @@ class NoteDetail extends React.Component {
key={index}
style={{zIndex: isActive ? 5 : 4}}
>
<div styleName='tabView-top'>
<input styleName='tabView-top-name'
placeholder='Filename including extensions...'
value={snippet.name}
readOnly
/>
<button styleName='tabView-top-mode'
>
{snippet.mode == null
? 'Not selected'
: syntax.name
}&nbsp;
</button>
</div>
{snippet.mode === 'markdown'
? <MarkdownEditor styleName='tabView-content'
config={config}

View File

@@ -60,31 +60,13 @@
.tabList-plusButton
navButtonColor()
width 30px
.tabView
absolute left right bottom
top 110px
.tabView-top
absolute top left right
height 30px
border-bottom $ui-border
display flex
box-sizing border-box
.tabView-top-name
flex 1
border none
padding 0 10px
font-size 14px
.tabView-top-mode
width 110px
padding 0
border none
border-left $ui-border
colorDefaultButton()
color $ui-inactive-text-color
pointer-events none
.tabView-content
absolute left right bottom
top 30px
absolute top left right bottom
box-sizing border-box
height 100%
width 100%

View File

@@ -28,7 +28,6 @@
color white
background-color transparent
.border
absolute top bottom left right
border-style solid

17
browser/lib/context.js Normal file
View File

@@ -0,0 +1,17 @@
const { remote } = require('electron')
const { Menu, MenuItem } = remote
function popup (templates) {
let menu = new Menu()
templates.forEach((item) => {
menu.append(new MenuItem(item))
})
menu.popup(remote.getCurrentWindow())
}
const context = {
popup
}
module.export = context
export default context

View File

@@ -10,6 +10,7 @@ import dataApi from 'browser/main/lib/dataApi'
import { hashHistory } from 'react-router'
import ee from 'browser/main/lib/eventEmitter'
import CodeMirror from 'codemirror'
import SnippetTab from './SnippetTab'
function pass (name) {
switch (name) {
@@ -238,6 +239,10 @@ class SnippetNoteDetail extends React.Component {
}
handleTabPlusButtonClick (e) {
this.addSnippet()
}
addSnippet () {
let { note } = this.state
note.snippets = note.snippets.concat([{
@@ -245,9 +250,13 @@ class SnippetNoteDetail extends React.Component {
mode: 'text',
content: ''
}])
let snippetIndex = note.snippets.length - 1
this.setState({
note
note,
snippetIndex
}, () => {
this.refs['tab-' + snippetIndex].startRenaming()
})
}
@@ -279,15 +288,19 @@ class SnippetNoteDetail extends React.Component {
let snippets = this.state.note.snippets.slice()
snippets.splice(index, 1)
this.state.note.snippets = snippets
let snippetIndex = this.state.snippetIndex >= snippets.length
? snippets.length - 1
: this.state.snippetIndex
this.setState({
note: this.state.note
note: this.state.note,
snippetIndex
})
}
handleNameInputChange (e, index) {
renameSnippetByIndex (index, name) {
let snippets = this.state.note.snippets.slice()
snippets[index].name = e.target.value
let syntax = CodeMirror.findModeByFileName(e.target.value.trim())
snippets[index].name = name
let syntax = CodeMirror.findModeByFileName(name.trim())
let mode = syntax != null ? syntax.name : null
if (mode != null) snippets[index].mode = mode
this.state.note.snippets = snippets
@@ -339,8 +352,62 @@ class SnippetNoteDetail extends React.Component {
}
}
handleDeleteKeyDown (e) {
if (e.keyCode === 27) this.handleDeleteCancelButtonClick(e)
handleKeyDown (e) {
switch (e.keyCode) {
case 9:
if (e.ctrlKey && !e.shiftKey) {
e.preventDefault()
this.jumpNextTab()
} else if (e.ctrlKey && e.shiftKey) {
e.preventDefault()
this.jumpPrevTab()
} else if (!e.ctrlKey && !e.shiftKey && e.target === this.refs.description) {
e.preventDefault()
this.focusEditor()
}
break
case 76:
let shouldFocus = global.process.platform === 'darwin'
? e.metaKey
: e.ctrlKey
if (shouldFocus) {
e.preventDefault()
this.focus()
}
break
case 84:
{
let shouldFocus = global.process.platform === 'darwin'
? e.metaKey
: e.ctrlKey
if (e.shouldFocus) {
e.preventDefault()
this.addSnippet()
}
}
}
}
jumpNextTab () {
this.setState({
snippetIndex: (this.state.snippetIndex + 1) % this.state.note.snippets.length
}, () => {
this.focusEditor()
})
}
jumpPrevTab () {
this.setState({
snippetIndex: (this.state.snippetIndex - 1 + this.state.note.snippets.length) % this.state.note.snippets.length
}, () => {
this.focusEditor()
})
}
focusEditor () {
console.log('code-' + this.state.snippetIndex)
this.refs['code-' + this.state.snippetIndex].focus()
}
render () {
@@ -354,31 +421,19 @@ class SnippetNoteDetail extends React.Component {
let tabList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
return <div styleName={isActive
? 'tabList-item--active'
: 'tabList-item'
}
return <SnippetTab
key={index}
>
<button styleName='tabList-item-button'
onClick={(e) => this.handleTabButtonClick(e, index)}
>
{snippet.name.trim().length > 0
? snippet.name
: <span styleName='tabList-item-unnamed'>
Unnamed
</span>
}
</button>
{note.snippets.length > 1 &&
<button styleName='tabList-item-deleteButton'
onClick={(e) => this.handleTabDeleteButtonClick(e, index)}
>
<i className='fa fa-times'/>
</button>
}
</div>
ref={'tab-' + index}
snippet={snippet}
isActive={isActive}
onClick={(e) => this.handleTabButtonClick(e, index)}
onDelete={(e) => this.handleTabDeleteButtonClick(e, index)}
onRename={(name) => this.renameSnippetByIndex(index, name)}
isDeletable={note.snippets.length > 1}
/>
})
let viewList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
@@ -389,22 +444,6 @@ class SnippetNoteDetail extends React.Component {
key={index}
style={{zIndex: isActive ? 5 : 4}}
>
<div styleName='tabView-top'>
<input styleName='tabView-top-name'
placeholder='Filename including extensions...'
value={snippet.name}
onChange={(e) => this.handleNameInputChange(e, index)}
/>
<button styleName='tabView-top-mode'
onClick={(e) => this.handleModeButtonClick(index)(e)}
>
{snippet.mode == null
? 'Select Syntax...'
: syntax.name
}&nbsp;
<i className='fa fa-caret-down'/>
</button>
</div>
{snippet.mode === 'markdown'
? <MarkdownEditor styleName='tabView-content'
value={snippet.content}
@@ -432,6 +471,7 @@ class SnippetNoteDetail extends React.Component {
<div className='NoteDetail'
style={this.props.style}
styleName='root'
onKeyDown={(e) => this.handleKeyDown(e)}
>
<div styleName='info'>
<div styleName='info-left'>
@@ -478,8 +518,8 @@ class SnippetNoteDetail extends React.Component {
</div>
<div styleName='body'>
<div styleName='body-description'>
<textarea styleName='body-description-textarea'
<div styleName='description'>
<textarea
style={{
fontFamily: config.preview.fontFamily,
fontSize: parseInt(config.preview.fontSize, 10)
@@ -491,8 +531,10 @@ class SnippetNoteDetail extends React.Component {
/>
</div>
<div styleName='tabList'>
{tabList}
<button styleName='tabList-plusButton'
<div styleName='list'>
{tabList}
</div>
<button styleName='plusButton'
onClick={(e) => this.handleTabPlusButtonClick(e)}
>
<i className='fa fa-plus'/>

View File

@@ -62,12 +62,12 @@ $info-height = 75px
absolute bottom left right
top $info-height
.body-description
.body .description
absolute top left right
height 80px
border-bottom $ui-border
.body-description-textarea
.body .description textarea
display block
height 100%
width 100%
@@ -83,67 +83,23 @@ $info-height = 75px
border-bottom $ui-border
display flex
background-color $ui-backgroundColor
.tabList-item
position relative
.tabList .list
flex 1
display flex
overflow hidden
border-right $ui-border
&:hover
.tabList-item-deleteButton
color $ui-inactive-text-color
&:hover
background-color darken($ui-backgroundColor, 15%)
&:active
color white
background-color $ui-active-color
.tabList-item--active
@extend .tabList-item
.tabList-item-button
border-color $brand-color
.tabList-item-button
width 100%
height 29px
navButtonColor()
border-left 4px solid transparent
.tabList-item-deleteButton
position absolute
top 5px
height 20px
right 5px
width 20px
text-align center
border none
padding 0
color transparent
background-color transparent
border-radius 2px
.tabList-plusButton
.tabList .plusButton
navButtonColor()
width 30px
.tabView
absolute left right bottom
top 110px
.tabView-top
absolute top left right
height 30px
border-bottom $ui-border
display flex
.tabView-top-name
flex 1
border none
padding 0 10px
font-size 14px
.tabView-top-mode
width 110px
padding 0
border none
border-left $ui-border
colorDefaultButton()
color $ui-inactive-text-color
&:hover
color $ui-text-color
.tabView-content
absolute left right bottom
top 30px
absolute top left right bottom
body[data-theme="dark"]
.root
@@ -178,10 +134,10 @@ body[data-theme="dark"]
.info-right-button-tooltip
darkTooltip()
.body-description
.body .description
border-bottom-color $ui-dark-borderColor
.body-description-textarea
.body .description textarea
background-color $ui-dark-button--hover-backgroundColor
color white
@@ -190,41 +146,12 @@ body[data-theme="dark"]
border-bottom-color $ui-dark-borderColor
background-color $ui-dark-backgroundColor
.tabList-item
.tabList .list
border-color $ui-dark-borderColor
&:hover
background-color $ui-dark-button--hover-backgroundColor
.tabList-item-deleteButton
color $ui-dark-inactive-text-color
&:hover
background-color darken($ui-dark-button--hover-backgroundColor, 15%)
&:active
color white
background-color $ui-dark-button--active-backgroundColor
.tabList-item--active
border-color $ui-dark-borderColor
.tabList-item-button
border-color $brand-color
&:hover
background-color $ui-dark-button--hover-backgroundColor
.tabList-item-deleteButton
color $ui-dark-inactive-text-color
&:hover
background-color darken($ui-dark-button--hover-backgroundColor, 15%)
&:active
color white
background-color $ui-dark-button--active-backgroundColor
.tabList-item-button
.tabList .plusButton
navDarkButtonColor()
border-left 4px solid transparent
.tabList-plusButton
navDarkButtonColor()
.tabView-top
border-color $ui-dark-borderColor
.tabView-top-name
border-color $ui-dark-borderColor
color $ui-dark-text-color
background-color $ui-dark-button--hover-backgroundColor
.tabView-top-mode
border-color $ui-dark-borderColor
background-color $dark-default-button-background

View File

@@ -0,0 +1,131 @@
import React, { PropTypes } from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './SnippetTab.styl'
import context from 'browser/lib/context'
class SnippetTab extends React.Component {
constructor (props) {
super(props)
this.state = {
isRenaming: false,
name: props.snippet.name
}
}
componentWillUpdate (nextProps) {
if (nextProps.snippet.name !== this.props.snippet.name) {
this.setState({
name: nextProps.snippet.name
})
}
}
handleClick (e) {
this.props.onClick(e)
}
handleContextMenu (e) {
context.popup([
{
label: 'Rename',
click: (e) => this.handleRenameClick(e)
}
])
}
handleRenameClick (e) {
this.startRenaming()
}
handleNameInputBlur (e) {
this.handleRename()
}
handleNameInputChange (e) {
this.setState({
name: e.target.value
})
}
handleNameInputKeyDown (e) {
switch (e.keyCode) {
case 13:
this.handleRename()
break
case 27:
this.setState({
name: this.props.snippet.name,
isRenaming: false
})
break
}
}
handleRename () {
this.setState({
isRenaming: false
}, () => {
if (this.props.snippet.name !== this.state.name) {
this.props.onRename(this.state.name)
}
})
}
handleDeleteButtonClick (e) {
this.props.onDelete(e)
}
startRenaming () {
this.setState({
isRenaming: true
}, () => {
this.refs.name.focus()
this.refs.name.select()
})
}
render () {
let { isActive, snippet, isDeletable } = this.props
return (
<div styleName={isActive
? 'root--active'
: 'root'
}
>
{!this.state.isRenaming
? <button styleName='button'
onClick={(e) => this.handleClick(e)}
onContextMenu={(e) => this.handleContextMenu(e)}
>
{snippet.name.trim().length > 0
? snippet.name
: <span styleName='button-unnamed'>
Unnamed
</span>
}
</button>
: <input styleName='input'
ref='name'
value={this.state.name}
onChange={(e) => this.handleNameInputChange(e)}
onBlur={(e) => this.handleNameInputBlur(e)}
onKeyDown={(e) => this.handleNameInputKeyDown(e)}
/>
}
{isDeletable &&
<button styleName='deleteButton'
onClick={(e) => this.handleDeleteButtonClick(e)}
>
<i className='fa fa-times'/>
</button>
}
</div>
)
}
}
SnippetTab.propTypes = {
}
export default CSSModules(SnippetTab, styles)

View File

@@ -0,0 +1,102 @@
.root
position relative
flex 1
overflow hidden
border-right $ui-border
&:last-child
border-right none
&:hover
.deleteButton
color $ui-inactive-text-color
&:hover
background-color darken($ui-backgroundColor, 15%)
&:active
color white
background-color $ui-active-color
.root--active
@extend .root
min-width 100px
.button
border-color $brand-color
.button
width 100%
height 29px
overflow ellipsis
text-align left
padding-right 30px
border none
background-color transparent
transition 0.15s
border-left 4px solid transparent
&:hover
background-color $ui-button--hover-backgroundColor
&:active, &:active:hover
border-color $brand-color
.deleteButton
position absolute
top 5px
height 20px
right 5px
width 20px
text-align center
border none
padding 0
color transparent
background-color transparent
border-radius 2px
.input
height 29px
border $ui-active-color
padding 0 5px
width 100%
outline none
body[data-theme="dark"]
.root
color $ui-dark-text-color
border-color $ui-dark-borderColor
&:hover
background-color $ui-dark-button--hover-backgroundColor
.deleteButton
color $ui-dark-inactive-text-color
&:hover
background-color darken($ui-dark-button--hover-backgroundColor, 15%)
&:active
color white
background-color $ui-dark-button--active-backgroundColor
.root--active
color $ui-dark-text-color
border-color $ui-dark-borderColor
.button
border-color $brand-color
&:hover
background-color $ui-dark-button--hover-backgroundColor
.deleteButton
color $ui-dark-inactive-text-color
&:hover
background-color darken($ui-dark-button--hover-backgroundColor, 15%)
&:active
color white
background-color $ui-dark-button--active-backgroundColor
.button
border none
color $ui-dark-text-color
background-color transparent
transition color background-color 0.15s
border-left 4px solid transparent
&:hover
color white
background-color $ui-dark-button--hover-backgroundColor
&:active
color $ui-dark-button--active-color
&:active, &:active:hover
color $ui-dark-button--active-color
.input
background-color $ui-dark-button--hover-backgroundColor
color white

View File

@@ -32,6 +32,9 @@
background-color transparent
border none
color $ui-inactive-text-color
transition 0.15s
&:active, &:active:hover
color $ui-active-color
&:hover
color $ui-text-color
.control-button-tooltip
@@ -67,11 +70,24 @@
cursor pointer
transition background-color 0.15s
&:hover
background-color alpha($ui-active-color, 10%)
background-color alpha($ui-active-color, 20%)
&:active
background-color $ui-active-color
color white
.item-title
.item-title-empty
.item-title-icon
.item-bottom-tagIcon
.item-bottom-tagList-empty
.item-bottom-time
color white
.item-bottom-tagList-item
background-color transparent
color white
.item--active
@extend .item
background-color alpha($ui-active-color, 100%)
background-color $ui-active-color
color white
.item-title
.item-title-empty
@@ -84,7 +100,7 @@
background-color transparent
color white
&:hover
background-color alpha($ui-active-color, 100%)
background-color $ui-active-color
.item-border
absolute top bottom left right
@@ -174,7 +190,7 @@ body[data-theme="dark"]
.item-bottom-tagList-empty
color white
&:hover
background-color alpha($ui-active-color, 100%)
background-color $ui-active-color
.item-title
color $ui-dark-text-color

View File

@@ -81,13 +81,14 @@ class NoteList extends React.Component {
}
// Auto scroll
if (_.isString(location.query.key) && prevProps.location.query.key !== location.query.key) {
if (_.isString(location.query.key) && prevProps.location.query.key === location.query.key) {
let targetIndex = _.findIndex(this.notes, (note) => {
return note != null && note.storage + '-' + note.key === location.query.key
})
if (targetIndex > -1) {
let list = this.refs.list
let item = list.childNodes[targetIndex]
if (item == null) return false
let overflowBelow = item.offsetTop + item.clientHeight - list.clientHeight - list.scrollTop > 0

View File

@@ -5,6 +5,7 @@
position relative
height 26px
width 100%
transition 0.15s
&:hover
background-color $ui-button--hover-backgroundColor
&:active

View File

@@ -37,6 +37,7 @@
border none
border-bottom solid 1px $border-color
border-radius 2px
background-color transparent
outline none
vertical-align middle
font-size 18px
@@ -74,3 +75,5 @@ body[data-theme="dark"]
.control-input
border-color $ui-dark-borderColor
color white

View File

@@ -37,6 +37,7 @@
border none
border-bottom solid 1px $border-color
border-radius 2px
background-color transparent
outline none
vertical-align middle
font-size 18px

View File

@@ -68,7 +68,6 @@ colorDefaultButton()
&:hover
background-color $default-button-background--hover
&:active
background-color $default-button-background--active
&:active:hover
background-color $default-button-background--active
@@ -83,9 +82,8 @@ colorPrimaryButton()
&:hover
background-color $primary-button-background--hover
&:active
background-color $primary-button-background--active
&:active:hover
background-color $primary-button-background--activ
background-color $primary-button-background--active
// Danger button(Brand color)
$danger-button-background = #c9302c
@@ -98,7 +96,6 @@ colorDangerButton()
&:hover
background-color $danger-button-background--hover
&:active
background-color $danger-button-background--active
&:active:hover
background-color $danger-button-background--active
@@ -113,9 +110,6 @@ navButtonColor()
transition color background-color 0.15s
&:hover
background-color $ui-button--hover-backgroundColor
&:active
background-color $ui-button--active-backgroundColor
color $ui-button--active-color
&:active, &:active:hover
background-color $ui-button--active-backgroundColor
color $ui-button--active-color
@@ -159,7 +153,6 @@ colorDarkDefaultButton()
&:hover
background-color $dark-default-button-background--hover
&:active
background-color $ui-dark-button--active-backgroundColor
&:active:hover
background-color $ui-dark-button--active-backgroundColor
@@ -172,7 +165,6 @@ colorDarkDangerButton()
&:hover
background-color $dark-danger-button-background--hover
&:active
background-color $dark-danger-button-background--active
&:active:hover
background-color $dark-danger-button-background--active
@@ -180,14 +172,12 @@ navDarkButtonColor()
border none
color $ui-dark-button-color
background-color transparent
transition color background-color 0.15s
transition color background-color 0.15s
&:hover
color white
background-color $ui-dark-button--hover-backgroundColor
&:active
background-color $ui-dark-button--active-backgroundColor
color $ui-dark-button--active-color
&:active, &:active:hover
&:active:hover
background-color $ui-dark-button--active-backgroundColor
color $ui-dark-button--active-color