mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 01:36:22 +00:00
add unsaved list & move new post button to top bar
This commit is contained in:
@@ -138,22 +138,15 @@ export default class ArticleDetail extends React.Component {
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.activeArticle == null || this.props.activeArticle == null || nextProps.activeArticle.key !== this.props.activeArticle.key) {
|
||||
let nextArticle = nextProps.activeArticle
|
||||
let nextModified = nextArticle != null ? _.findWhere(nextProps.modified, {key: nextArticle.key}) : null
|
||||
let nextArticle = nextProps.activeArticle
|
||||
let nextModified = nextArticle != null ? _.findWhere(nextProps.modified, {key: nextArticle.key}) : null
|
||||
|
||||
let article = Object.assign({content: ''}, nextProps.activeArticle, nextModified)
|
||||
let nextState = {
|
||||
article,
|
||||
previewMode: false
|
||||
}
|
||||
|
||||
if (article.content.trim().length > 0 && article.mode === 'markdown') {
|
||||
nextState.previewMode = true
|
||||
}
|
||||
|
||||
this.setState(nextState)
|
||||
let article = Object.assign({content: ''}, nextProps.activeArticle, nextModified)
|
||||
let nextState = {
|
||||
article
|
||||
}
|
||||
|
||||
this.setState(nextState)
|
||||
}
|
||||
|
||||
editArticle () {
|
||||
@@ -404,12 +397,12 @@ export default class ArticleDetail extends React.Component {
|
||||
}
|
||||
|
||||
ArticleDetail.propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
status: PropTypes.shape(),
|
||||
activeArticle: PropTypes.shape(),
|
||||
modified: PropTypes.array,
|
||||
tags: PropTypes.array,
|
||||
user: PropTypes.shape(),
|
||||
folders: PropTypes.array,
|
||||
tags: PropTypes.array,
|
||||
dispatch: PropTypes.func
|
||||
modified: PropTypes.array,
|
||||
activeArticle: PropTypes.shape()
|
||||
}
|
||||
ArticleDetail.prototype.linkState = linkState
|
||||
|
||||
@@ -85,12 +85,16 @@ export default class ArticleList extends React.Component {
|
||||
}
|
||||
|
||||
handleArticleListKeyDown (e) {
|
||||
console.log(e.keyCode)
|
||||
if (e.metaKey || e.ctrlKey) return true
|
||||
|
||||
if (e.keyCode === 65) {
|
||||
if (e.keyCode === 65 && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('nav-new-post')
|
||||
remote.getCurrentWebContents().send('top-new-post')
|
||||
}
|
||||
|
||||
if (e.keyCode === 65 && e.shiftKey) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('nav-new-folder')
|
||||
}
|
||||
|
||||
if (e.keyCode === 68) {
|
||||
@@ -129,7 +133,7 @@ export default class ArticleList extends React.Component {
|
||||
article = Object.assign({}, article, modifiedArticle)
|
||||
}
|
||||
let tagElements = Array.isArray(article.tags) && article.tags.length > 0
|
||||
? article.tags.map(tag => {
|
||||
? article.tags.slice().map(tag => {
|
||||
return (<TagLink key={tag} tag={tag}/>)
|
||||
})
|
||||
: (<span>Not tagged yet</span>)
|
||||
@@ -189,9 +193,9 @@ export default class ArticleList extends React.Component {
|
||||
}
|
||||
|
||||
ArticleList.propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
folders: PropTypes.array,
|
||||
articles: PropTypes.array,
|
||||
modified: PropTypes.array,
|
||||
activeArticle: PropTypes.shape(),
|
||||
dispatch: PropTypes.func
|
||||
activeArticle: PropTypes.shape()
|
||||
}
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { findWhere } from 'lodash'
|
||||
import { setSearchFilter, switchFolder, saveArticle } from '../actions'
|
||||
import { setSearchFilter, switchFolder, uncacheArticle, saveAllArticles, switchArticle, clearSearch } from '../actions'
|
||||
import { openModal, isModalOpen } from 'browser/lib/modal'
|
||||
import FolderMark from 'browser/components/FolderMark'
|
||||
import Preferences from '../modal/Preferences'
|
||||
import CreateNewFolder from '../modal/CreateNewFolder'
|
||||
import keygen from 'browser/lib/keygen'
|
||||
import _ from 'lodash'
|
||||
import ModeIcon from 'browser/components/ModeIcon'
|
||||
|
||||
const ipc = require('electron').ipcRenderer
|
||||
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
|
||||
const preferenceTutorialElement = (
|
||||
<svg width='300' height='300' className='tutorial'>
|
||||
@@ -29,7 +31,7 @@ c-4,0-7.9,0-11.9-0.1C164,294,164,297,165.9,297L165.9,297z'/>
|
||||
const newPostTutorialElement = (
|
||||
<svg width='900' height='900' className='tutorial'>
|
||||
<text x='290' y='155' fill={BRAND_COLOR} fontSize='24'>Create a new post!!</text>
|
||||
<text x='300' y='180' fill={BRAND_COLOR} fontSize='16' children={`press \`${process.platform === 'darwin' ? '⌘' : '^'} + Enter\` or \`a\``}/>
|
||||
<text x='300' y='180' fill={BRAND_COLOR} fontSize='16' children={`press \`${OSX === 'darwin' ? '⌘' : '^'} + Enter\` or \`a\``}/>
|
||||
<svg x='130' y='-20' width='400' height='400'>
|
||||
<path fill='white' d='M56.2,132.5c11.7-2.9,23.9-6,36.1-4.1c8.7,1.4,16.6,5.5,23.7,10.5c13.3,9.4,24.5,21.5,40.2,27
|
||||
c1.8,0.6,2.6-2.3,0.8-2.9c-17.1-6-28.9-20.3-44-29.7c-7-4.4-14.8-7.4-23-8.2c-11.7-1.1-23.3,1.7-34.5,4.5
|
||||
@@ -62,10 +64,6 @@ c-3.4-6.1-8.2-11.3-13.8-15.4C50.2,11.6,31,10.9,15.3,19C13.6,19.8,15.1,22.4,16.8,
|
||||
export default class ArticleNavigator extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.newPostHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleNewPostButtonClick(e)
|
||||
}
|
||||
this.newFolderHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleNewFolderButton(e)
|
||||
@@ -73,12 +71,10 @@ export default class ArticleNavigator extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
ipc.on('nav-new-post', this.newPostHandler)
|
||||
ipc.on('nav-new-folder', this.newFolderHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
ipc.removeListener('nav-new-post', this.newPostHandler)
|
||||
ipc.removeListener('nav-new-folder', this.newFolderHandler)
|
||||
}
|
||||
|
||||
@@ -86,30 +82,6 @@ export default class ArticleNavigator extends React.Component {
|
||||
openModal(Preferences)
|
||||
}
|
||||
|
||||
handleNewPostButtonClick (e) {
|
||||
let { dispatch, folders, status } = this.props
|
||||
let { targetFolders } = status
|
||||
|
||||
let isFolderFilterApplied = targetFolders.length > 0
|
||||
let FolderKey = isFolderFilterApplied
|
||||
? targetFolders[0].key
|
||||
: folders[0].key
|
||||
|
||||
let newArticle = {
|
||||
key: keygen(),
|
||||
title: '',
|
||||
content: '',
|
||||
mode: 'markdown',
|
||||
tags: [],
|
||||
FolderKey: FolderKey,
|
||||
craetedAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
}
|
||||
|
||||
dispatch(saveArticle(newArticle.key, newArticle, true))
|
||||
if (isFolderFilterApplied) dispatch(switchFolder(targetFolders[0].name))
|
||||
}
|
||||
|
||||
handleNewFolderButton (e) {
|
||||
let { user } = this.props
|
||||
openModal(CreateNewFolder, {user: user})
|
||||
@@ -127,11 +99,52 @@ export default class ArticleNavigator extends React.Component {
|
||||
dispatch(setSearchFilter(''))
|
||||
}
|
||||
|
||||
handleUnsavedItemClick (article) {
|
||||
let { dispatch } = this.props
|
||||
return e => {
|
||||
let { articles } = this.props
|
||||
let isInArticleList = articles.some(_article => _article.key === article.key)
|
||||
if (!isInArticleList) dispatch(clearSearch())
|
||||
dispatch(switchArticle(article.key))
|
||||
}
|
||||
}
|
||||
|
||||
handleUncacheButtonClick (article) {
|
||||
let { dispatch } = this.props
|
||||
return e => {
|
||||
dispatch(uncacheArticle(article.key))
|
||||
}
|
||||
}
|
||||
|
||||
handleSaveAllClick (e) {
|
||||
let { dispatch } = this.props
|
||||
dispatch(saveAllArticles())
|
||||
}
|
||||
|
||||
render () {
|
||||
let { status, user, folders, allArticles } = this.props
|
||||
let { status, user, folders, allArticles, modified, activeArticle } = this.props
|
||||
let { targetFolders } = status
|
||||
if (targetFolders == null) targetFolders = []
|
||||
|
||||
let modifiedElements = modified.map(modifiedArticle => {
|
||||
let originalArticle = _.findWhere(allArticles, {key: modifiedArticle.key})
|
||||
if (originalArticle == null) return false
|
||||
let combinedArticle = Object.assign({}, originalArticle, modifiedArticle)
|
||||
|
||||
let className = 'ArticleNavigator-unsaved-list-item'
|
||||
if (activeArticle && activeArticle.key === combinedArticle.key) className += ' active'
|
||||
|
||||
return (
|
||||
<div key={modifiedArticle.key} onClick={e => this.handleUnsavedItemClick(combinedArticle)(e)} className={className}>
|
||||
<div className='ArticleNavigator-unsaved-list-item-label'>
|
||||
<ModeIcon mode={combinedArticle.mode}/>
|
||||
{combinedArticle.title}
|
||||
</div>
|
||||
<button onClick={e => this.handleUncacheButtonClick(combinedArticle)(e)} className='ArticleNavigator-unsaved-list-item-discard-button'><i className='fa fa-times'/></button>
|
||||
</div>
|
||||
)
|
||||
}).filter(modifiedArticle => modifiedArticle).sort((a, b) => a.updatedAt - b.updatedAt)
|
||||
|
||||
let folderElememts = folders.map((folder, index) => {
|
||||
let isActive = findWhere(targetFolders, {key: folder.key})
|
||||
let articleCount = allArticles.filter(article => article.FolderKey === folder.key && article.status !== 'NEW').length
|
||||
@@ -157,22 +170,27 @@ export default class ArticleNavigator extends React.Component {
|
||||
|
||||
</div>
|
||||
|
||||
<div className='controlSection'>
|
||||
<button onClick={e => this.handleNewPostButtonClick(e)} className='newPostBtn'>
|
||||
New Post
|
||||
<span className='tooltip'>Create a new Post ({process.platform === 'darwin' ? '⌘' : '^'} + n)</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newPostTutorialElement : null}
|
||||
|
||||
<div className='ArticleNavigator-unsaved'>
|
||||
<div className='ArticleNavigator-unsaved-header'>Work in progress</div>
|
||||
<div className='ArticleNavigator-unsaved-list'>
|
||||
{modifiedElements.length > 0
|
||||
? modifiedElements
|
||||
: (
|
||||
<div className='ArticleNavigator-unsaved-list-empty'>Empty list</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className='ArticleNavigator-unsaved-control'>
|
||||
<button onClick={e => this.handleSaveAllClick()} className='ArticleNavigator-unsaved-control-save-all-button' disabled={modifiedElements.length === 0}>Save all</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='folders'>
|
||||
<div className='header'>
|
||||
<div className='ArticleNavigator-folders'>
|
||||
<div className='ArticleNavigator-folders-header'>
|
||||
<div className='title'>Folders</div>
|
||||
<button onClick={e => this.handleNewFolderButton(e)} className='addBtn'>
|
||||
<i className='fa fa-fw fa-plus'/>
|
||||
<span className='tooltip'>Create a new folder ({process.platform === 'darwin' ? '⌘' : '^'} + Shift + n)</span>
|
||||
<span className='tooltip'>Create a new folder ({OSX === 'darwin' ? '⌘' : '^'} + Shift + n)</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newFolderTutorialElement : null}
|
||||
@@ -189,12 +207,17 @@ export default class ArticleNavigator extends React.Component {
|
||||
}
|
||||
|
||||
ArticleNavigator.propTypes = {
|
||||
user: PropTypes.object,
|
||||
folders: PropTypes.array,
|
||||
allArticles: PropTypes.array,
|
||||
dispatch: PropTypes.func,
|
||||
status: PropTypes.shape({
|
||||
folderId: PropTypes.number
|
||||
}),
|
||||
dispatch: PropTypes.func
|
||||
user: PropTypes.object,
|
||||
folders: PropTypes.array,
|
||||
allArticles: PropTypes.array,
|
||||
articles: PropTypes.array,
|
||||
modified: PropTypes.array,
|
||||
activeArticle: PropTypes.shape({
|
||||
key: PropTypes.string
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,15 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import ExternalLink from 'browser/components/ExternalLink'
|
||||
import { setSearchFilter, clearSearch, toggleOnlyUnsavedFilter, toggleTutorial, saveAllArticles, switchArticle } from '../actions'
|
||||
import store from '../store'
|
||||
import { setSearchFilter, clearSearch, toggleTutorial, saveArticle, switchFolder } from '../actions'
|
||||
import { isModalOpen } from 'browser/lib/modal'
|
||||
import keygen from 'browser/lib/keygen'
|
||||
|
||||
const electron = require('electron')
|
||||
const remote = electron.remote
|
||||
const Menu = remote.Menu
|
||||
const MenuItem = remote.MenuItem
|
||||
const ipc = electron.ipcRenderer
|
||||
|
||||
const OSX = process.platform === 'darwin'
|
||||
|
||||
var menu = new Menu()
|
||||
var lastIndex = -1
|
||||
menu.append(new MenuItem({
|
||||
label: 'Show only unsaved',
|
||||
click: function () {
|
||||
store.dispatch(setSearchFilter('--unsaved'))
|
||||
}
|
||||
}))
|
||||
menu.append(new MenuItem({
|
||||
label: 'Go to an unsaved article',
|
||||
click: function () {
|
||||
lastIndex++
|
||||
let state = store.getState()
|
||||
let modified = state.articles.modified
|
||||
if (modified.length === 0) return
|
||||
if (modified.length <= lastIndex) {
|
||||
lastIndex = 0
|
||||
}
|
||||
store.dispatch(switchArticle(modified[lastIndex].key))
|
||||
}
|
||||
}))
|
||||
const OSX = global.process.platform === 'darwin'
|
||||
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
|
||||
@@ -74,6 +50,10 @@ export default class ArticleTopBar extends React.Component {
|
||||
if (isModalOpen()) return true
|
||||
this.focusInput(e)
|
||||
}
|
||||
this.newPostHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleNewPostButtonClick(e)
|
||||
}
|
||||
|
||||
this.state = {
|
||||
isTooltipHidden: true,
|
||||
@@ -101,6 +81,7 @@ export default class ArticleTopBar extends React.Component {
|
||||
|
||||
ipc.on('top-save-all', this.saveAllHandler)
|
||||
ipc.on('top-focus-search', this.focusSearchHandler)
|
||||
ipc.on('top-new-post', this.newPostHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
@@ -109,6 +90,7 @@ export default class ArticleTopBar extends React.Component {
|
||||
|
||||
ipc.removeListener('top-save-all', this.saveAllHandler)
|
||||
ipc.removeListener('top-focus-search', this.focusSearchHandler)
|
||||
ipc.removeListener('top-new-post', this.newPostHandler)
|
||||
}
|
||||
|
||||
handleTooltipRequest (e) {
|
||||
@@ -152,21 +134,29 @@ export default class ArticleTopBar extends React.Component {
|
||||
this.focusInput()
|
||||
}
|
||||
|
||||
handleOnlyUnsavedChange (e) {
|
||||
let { dispatch } = this.props
|
||||
handleNewPostButtonClick (e) {
|
||||
let { dispatch, folders, status } = this.props
|
||||
let { targetFolders } = status
|
||||
|
||||
dispatch(toggleOnlyUnsavedFilter())
|
||||
}
|
||||
let isFolderFilterApplied = targetFolders.length > 0
|
||||
let FolderKey = isFolderFilterApplied
|
||||
? targetFolders[0].key
|
||||
: folders[0].key
|
||||
|
||||
handleSaveAllButtonClick (e) {
|
||||
let { dispatch } = this.props
|
||||
let newArticle = {
|
||||
key: keygen(),
|
||||
title: '',
|
||||
content: '',
|
||||
mode: 'markdown',
|
||||
tags: [],
|
||||
FolderKey: FolderKey,
|
||||
craetedAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
}
|
||||
|
||||
dispatch(saveAllArticles())
|
||||
remote.getCurrentWebContents().send('list-focus')
|
||||
}
|
||||
|
||||
handleSaveMenuButtonClick (e) {
|
||||
menu.popup(590, 45)
|
||||
dispatch(saveArticle(newArticle.key, newArticle, true))
|
||||
if (isFolderFilterApplied) dispatch(switchFolder(targetFolders[0].name))
|
||||
remote.getCurrentWebContents().send('detail-edit')
|
||||
}
|
||||
|
||||
handleTutorialButtonClick (e) {
|
||||
@@ -176,7 +166,7 @@ export default class ArticleTopBar extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
let { status, modified } = this.props
|
||||
let { status } = this.props
|
||||
return (
|
||||
<div className='ArticleTopBar'>
|
||||
<div className='ArticleTopBar-left'>
|
||||
@@ -207,13 +197,11 @@ export default class ArticleTopBar extends React.Component {
|
||||
|
||||
{status.isTutorialOpen ? searchTutorialElement : null}
|
||||
|
||||
<div className={'ArticleTopBar-left-unsaved'}>
|
||||
<button onClick={e => this.handleSaveAllButtonClick(e)} className='ArticleTopBar-left-unsaved-save-button' disabled={modified.length === 0}>
|
||||
<i className='fa fa-save'/>
|
||||
<span className={'ArticleTopBar-left-unsaved-save-button-count' + (modified.length === 0 ? ' hide' : '')} children={modified.length}/>
|
||||
<span className='ArticleTopBar-left-unsaved-save-button-tooltip' children={`Save all ${modified.length} articles (${OSX ? '⌘ + Shift + s' : '^ + Shift + s'})`}></span>
|
||||
<div className={'ArticleTopBar-left-control'}>
|
||||
<button onClick={e => this.handleNewPostButtonClick(e)}>
|
||||
<i className='fa fa-plus'/>
|
||||
<span className='tooltip'>New Post ({OSX ? '⌘' : '^'} + n)</span>
|
||||
</button>
|
||||
<button onClick={e => this.handleSaveMenuButtonClick(e)} className='ArticleTopBar-left-unsaved-menu-button'><i className='fa fa-angle-down'/></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -260,10 +248,9 @@ export default class ArticleTopBar extends React.Component {
|
||||
}
|
||||
|
||||
ArticleTopBar.propTypes = {
|
||||
search: PropTypes.string,
|
||||
dispatch: PropTypes.func,
|
||||
status: PropTypes.shape({
|
||||
search: PropTypes.string
|
||||
}),
|
||||
modified: PropTypes.array
|
||||
folders: PropTypes.array
|
||||
}
|
||||
|
||||
@@ -64,23 +64,26 @@ class HomePage extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
let { dispatch, status, user, articles, allArticles, modified, activeArticle, folders, tags, filters } = this.props
|
||||
let { dispatch, status, user, articles, allArticles, modified, activeArticle, folders, tags } = this.props
|
||||
|
||||
return (
|
||||
<div className='HomePage'>
|
||||
<ArticleNavigator
|
||||
ref='nav'
|
||||
dispatch={dispatch}
|
||||
status={status}
|
||||
user={user}
|
||||
folders={folders}
|
||||
status={status}
|
||||
allArticles={allArticles}
|
||||
articles={articles}
|
||||
modified={modified}
|
||||
activeArticle={activeArticle}
|
||||
/>
|
||||
<ArticleTopBar
|
||||
ref='top'
|
||||
dispatch={dispatch}
|
||||
status={status}
|
||||
modified={modified}
|
||||
folders={folders}
|
||||
/>
|
||||
<ArticleList
|
||||
ref='list'
|
||||
@@ -88,19 +91,17 @@ class HomePage extends React.Component {
|
||||
folders={folders}
|
||||
articles={articles}
|
||||
modified={modified}
|
||||
status={status}
|
||||
activeArticle={activeArticle}
|
||||
/>
|
||||
<ArticleDetail
|
||||
ref='detail'
|
||||
dispatch={dispatch}
|
||||
user={user}
|
||||
activeArticle={activeArticle}
|
||||
modified={modified}
|
||||
folders={folders}
|
||||
status={status}
|
||||
tags={tags}
|
||||
filters={filters}
|
||||
user={user}
|
||||
folders={folders}
|
||||
modified={modified}
|
||||
activeArticle={activeArticle}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -208,12 +209,7 @@ function remap (state) {
|
||||
allArticles,
|
||||
modified,
|
||||
activeArticle,
|
||||
tags,
|
||||
filters: {
|
||||
folder: folderFilters,
|
||||
tag: tagFilters,
|
||||
text: textFilters
|
||||
}
|
||||
tags
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,11 +224,6 @@ HomePage.propTypes = {
|
||||
activeArticle: PropTypes.shape(),
|
||||
dispatch: PropTypes.func,
|
||||
folders: PropTypes.array,
|
||||
filters: PropTypes.shape({
|
||||
folder: PropTypes.array,
|
||||
tag: PropTypes.array,
|
||||
text: PropTypes.array
|
||||
}),
|
||||
tags: PropTypes.array
|
||||
}
|
||||
|
||||
|
||||
@@ -56,42 +56,91 @@ articleCount = #999
|
||||
&:active
|
||||
background-color brandColor
|
||||
border-color brandColor
|
||||
.controlSection
|
||||
height 88px
|
||||
padding 22px 15px
|
||||
margin-bottom 44px
|
||||
.tutorial
|
||||
fixed top left
|
||||
z-index 35
|
||||
pointer-event none
|
||||
font-style italic
|
||||
transition 0.1s
|
||||
&.hide
|
||||
opacity 0
|
||||
.newPostBtn
|
||||
position relative
|
||||
border none
|
||||
background-color brandColor
|
||||
color white
|
||||
height 44px
|
||||
width 170px
|
||||
border-radius 5px
|
||||
font-size 20px
|
||||
transition 0.1s
|
||||
z-index 30
|
||||
.tooltip
|
||||
tooltip()
|
||||
margin-left 48px
|
||||
margin-top -3px
|
||||
&:hover
|
||||
background-color lighten(brandColor, 7%)
|
||||
.tooltip
|
||||
opacity 1
|
||||
.folders, .members
|
||||
.header
|
||||
border-bottom 1px solid borderColor
|
||||
.ArticleNavigator-unsaved
|
||||
position absolute
|
||||
top 100px
|
||||
width 100%
|
||||
height 225px
|
||||
.ArticleNavigator-unsaved-header
|
||||
border-bottom 1px solid alpha(borderColor, 0.5)
|
||||
padding-bottom 5px
|
||||
clearfix()
|
||||
position relative
|
||||
z-index 30
|
||||
padding-left 10px
|
||||
font-size 18px
|
||||
line-height 22px
|
||||
margin-bottom 5px
|
||||
.ArticleNavigator-unsaved-list
|
||||
.ArticleNavigator-unsaved-list-item
|
||||
height 33px
|
||||
padding-left 15px
|
||||
clearfix()
|
||||
transition 0.1s
|
||||
cursor pointer
|
||||
overflow hidden
|
||||
&:hover
|
||||
background-color alpha(white, 0.05)
|
||||
&.active, &:active
|
||||
background-color alpha(lighten(brandColor, 25%), 70%)
|
||||
.ArticleNavigator-unsaved-list-item-label
|
||||
float left
|
||||
width 151px
|
||||
line-height 33px
|
||||
overflow ellipsis
|
||||
.ArticleNavigator-unsaved-list-item-discard-button
|
||||
float right
|
||||
width 33px
|
||||
line-height 30px
|
||||
height 33px
|
||||
border none
|
||||
background-color transparent
|
||||
color white
|
||||
font-size 18px
|
||||
opacity 0.5
|
||||
&:hover
|
||||
opacity 1
|
||||
.ArticleNavigator-unsaved-list-empty
|
||||
height 33px
|
||||
padding-left 15px
|
||||
color alpha(white, 0.4)
|
||||
transition 0.1s
|
||||
line-height 33px
|
||||
&:hover
|
||||
color alpha(white, 0.6)
|
||||
.ArticleNavigator-unsaved-control
|
||||
absolute bottom
|
||||
height 33px
|
||||
border-top 1px solid alpha(borderColor, 0.5)
|
||||
width 100%
|
||||
.ArticleNavigator-unsaved-control-save-all-button
|
||||
border none
|
||||
background-color transparent
|
||||
font-size 14px
|
||||
color brandColor
|
||||
padding-left 15px
|
||||
width 100%
|
||||
height 33px
|
||||
text-align left
|
||||
&:hover
|
||||
color lighten(brandColor, 15%)
|
||||
background-color alpha(white, 0.05)
|
||||
&:active
|
||||
color white
|
||||
&:disabled
|
||||
color alpha(brandColor, 0.5)
|
||||
&:hover
|
||||
color alpha(lighten(brandColor, 25%), 0.5)
|
||||
background-color transparent
|
||||
|
||||
|
||||
.ArticleNavigator-folders
|
||||
absolute bottom
|
||||
top 365px
|
||||
width 100%
|
||||
.ArticleNavigator-folders-header
|
||||
border-bottom 1px solid alpha(borderColor, 0.5)
|
||||
padding-bottom 5px
|
||||
margin-bottom 10px
|
||||
clearfix()
|
||||
position relative
|
||||
z-index 30
|
||||
@@ -124,11 +173,6 @@ articleCount = #999
|
||||
&:active
|
||||
background-color brandColor
|
||||
border-color brandColor
|
||||
.folders
|
||||
absolute bottom
|
||||
top 200px
|
||||
width 100%
|
||||
.header
|
||||
.tutorial
|
||||
position fixed
|
||||
z-index 35px
|
||||
@@ -136,7 +180,7 @@ articleCount = #999
|
||||
font-style italic
|
||||
.folderList
|
||||
absolute bottom
|
||||
top 38px
|
||||
top 33px
|
||||
overflow-y auto
|
||||
.folderList button
|
||||
height 33px
|
||||
@@ -149,23 +193,9 @@ articleCount = #999
|
||||
padding-left 15px
|
||||
overflow ellipsis
|
||||
&:hover
|
||||
background-color transparentify(white, 5%)
|
||||
background-color alpha(white, 0.05)
|
||||
&.active, &:active
|
||||
background-color transparentify(lighten(brandColor, 25%), 70%)
|
||||
background-color alpha(lighten(brandColor, 25%), 70%)
|
||||
.articleCount
|
||||
color articleCount
|
||||
font-size 12px
|
||||
.members
|
||||
.memberList>div
|
||||
height 33px
|
||||
width 200px
|
||||
margin-bottom 5px
|
||||
padding-left 15px
|
||||
.memberImage
|
||||
float left
|
||||
margin-top 5.5px
|
||||
border-radius 11px
|
||||
.memberProfileName
|
||||
float left
|
||||
line-height 33px
|
||||
margin-left 7px
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
bgColor = #E6E6E6
|
||||
inputBgColor = white
|
||||
iptFocusBorderColor = #369DCD
|
||||
|
||||
topBarBtnColor = #B3B3B3
|
||||
topBarBtnBgColor = #B3B3B3
|
||||
@@ -87,7 +86,7 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
line-height 33px
|
||||
z-index 0
|
||||
&:focus
|
||||
border-color iptFocusBorderColor
|
||||
border-color focusBorderColor
|
||||
i.fa.fa-search
|
||||
position absolute
|
||||
display block
|
||||
@@ -110,13 +109,15 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
line-height 20px
|
||||
text-align center
|
||||
padding 0
|
||||
&:focus
|
||||
color textColor
|
||||
&:hover
|
||||
color white
|
||||
background-color topBarBtnBgColor
|
||||
&:active
|
||||
color white
|
||||
background-color darken(topBarBtnBgColor, 35%)
|
||||
.ArticleTopBar-left-unsaved
|
||||
.ArticleTopBar-left-control
|
||||
line-height 33px
|
||||
float left
|
||||
height 33px
|
||||
@@ -132,40 +133,22 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
height 33px
|
||||
border-radius 16.5px
|
||||
transition 0.1s
|
||||
border 1px solid transparent
|
||||
&:hover
|
||||
color inherit
|
||||
color textColor
|
||||
&:active
|
||||
color inherit
|
||||
color textColor
|
||||
background-color lighten(topBarBtnBgColor, 15%)
|
||||
&:disabled
|
||||
color inactiveTextColor
|
||||
background transparent
|
||||
&:focus
|
||||
color focusBorderColor
|
||||
&.ArticleTopBar-left-unsaved-save-button
|
||||
position relative
|
||||
.ArticleTopBar-left-unsaved-save-button-count
|
||||
position absolute
|
||||
font-size 10px
|
||||
background-color brandColor
|
||||
color white
|
||||
height 14px
|
||||
width 14px
|
||||
line-height 14px
|
||||
border-radius 7px
|
||||
top 16px
|
||||
right -3px
|
||||
transition 0.15s
|
||||
&.hide
|
||||
transform scale(0)
|
||||
.ArticleTopBar-left-unsaved-save-button-tooltip
|
||||
tooltip()
|
||||
margin-top 30px
|
||||
margin-left -100px
|
||||
&:hover
|
||||
.ArticleTopBar-left-unsaved-save-button-tooltip
|
||||
opacity 1
|
||||
|
||||
color textColor
|
||||
.tooltip
|
||||
tooltip()
|
||||
&:hover
|
||||
.tooltip
|
||||
opacity 1
|
||||
&>.ArticleTopBar-right
|
||||
float right
|
||||
&>button
|
||||
@@ -183,7 +166,7 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
border 1px solid bgColor
|
||||
transition 0.1s
|
||||
&:focus
|
||||
border-color focusBorderColor
|
||||
background-color lighten(infoBtnActiveBgColor, 15%)
|
||||
.tooltip
|
||||
tooltip()
|
||||
margin-left -50px
|
||||
|
||||
Reference in New Issue
Block a user