diff --git a/browser/components/SideNavFilter.styl b/browser/components/SideNavFilter.styl
index 1da8c7e4..d5435a16 100644
--- a/browser/components/SideNavFilter.styl
+++ b/browser/components/SideNavFilter.styl
@@ -1,5 +1,5 @@
.menu
- margin-bottom 30px
+ margin-bottom 20px
.menu-button
navButtonColor()
diff --git a/browser/components/StorageList.styl b/browser/components/StorageList.styl
index 474f896b..61fe195c 100644
--- a/browser/components/StorageList.styl
+++ b/browser/components/StorageList.styl
@@ -1,7 +1,5 @@
.storageList
- absolute left right
- bottom 37px
- top 180px
+ margin-bottom 37px
overflow-y auto
.storageList-folded
diff --git a/browser/main/SideNav/PreferenceButton.styl b/browser/main/SideNav/PreferenceButton.styl
index 54513cb6..12cb9267 100644
--- a/browser/main/SideNav/PreferenceButton.styl
+++ b/browser/main/SideNav/PreferenceButton.styl
@@ -1,8 +1,5 @@
.top-menu-preference
navButtonColor()
- position absolute
- top 22px
- right 10px
width 2em
background-color transparent
&:hover
diff --git a/browser/main/SideNav/SearchButton.js b/browser/main/SideNav/SearchButton.js
new file mode 100644
index 00000000..e9643128
--- /dev/null
+++ b/browser/main/SideNav/SearchButton.js
@@ -0,0 +1,22 @@
+import PropTypes from 'prop-types'
+import React from 'react'
+import CSSModules from 'browser/lib/CSSModules'
+import styles from './SearchButton.styl'
+import i18n from 'browser/lib/i18n'
+
+const SearchButton = ({ onClick, isActive }) => (
+
+)
+
+SearchButton.propTypes = {
+ onClick: PropTypes.func.isRequired,
+ isActive: PropTypes.bool
+}
+
+export default CSSModules(SearchButton, styles)
diff --git a/browser/main/SideNav/SearchButton.styl b/browser/main/SideNav/SearchButton.styl
new file mode 100644
index 00000000..76d4b806
--- /dev/null
+++ b/browser/main/SideNav/SearchButton.styl
@@ -0,0 +1,55 @@
+.top-menu-search
+ navButtonColor()
+ position relative
+ margin-right 6px
+ top 3px
+ width 2em
+ background-color transparent
+ &:hover
+ color $ui-button-default--active-backgroundColor
+ background-color transparent
+ .tooltip
+ opacity 1
+ &:active, &:active:hover
+ color $ui-button-default--active-backgroundColor
+
+.icon-search
+ width 16px
+
+body[data-theme="white"]
+ .top-menu-search
+ navWhiteButtonColor()
+ background-color transparent
+ &:hover
+ color #0B99F1
+ background-color transparent
+ &:active, &:active:hover
+ color #0B99F1
+ background-color transparent
+
+body[data-theme="dark"]
+ .top-menu-search
+ navDarkButtonColor()
+ background-color transparent
+ &:active
+ background-color alpha($ui-dark-button--active-backgroundColor, 20%)
+ background-color transparent
+ &:hover
+ background-color alpha($ui-dark-button--active-backgroundColor, 20%)
+ background-color transparent
+
+
+
+.tooltip
+ tooltip()
+ position absolute
+ pointer-events none
+ top 26px
+ left -20px
+ z-index 200
+ padding 5px
+ line-height normal
+ border-radius 2px
+ opacity 0
+ transition 0.1s
+ white-space nowrap
diff --git a/browser/main/SideNav/SideNav.styl b/browser/main/SideNav/SideNav.styl
index 9fa6d4fa..f6b4582b 100644
--- a/browser/main/SideNav/SideNav.styl
+++ b/browser/main/SideNav/SideNav.styl
@@ -18,7 +18,37 @@
display flex
text-align center
+.extra-buttons
+ position absolute
+ display flex
+ align-items center
+ justify-content flex-end
+ right 10px
+ top 24px
+.search
+ position relative
+ flex 1
+ display flex
+ max-height 0
+ overflow hidden
+ transition max-height .4s
+ margin -5px 10px 0
+ .search-input
+ flex 1
+ height 2em
+ vertical-align middle
+ font-size 14px
+ border solid 1px $border-color
+ border-radius 2px
+ padding 2px 6px
+ outline none
+ .search-clear
+ width 10px
+ position absolute
+ right 8px
+ top 9px
+ cursor pointer
.top-menu-label
margin-left 5px
@@ -98,6 +128,17 @@
.top-menu-preference
position absolute
left 7px
+ .search
+ height 28px
+ .search-input
+ display none
+ .search-clear
+ display none
+ .search-folded
+ width 16px
+ padding-left 4px
+ margin-bottom 8px
+ cursor pointer
body[data-theme="white"]
.root, .root--folded
diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js
index 640bedbf..de70861a 100644
--- a/browser/main/SideNav/index.js
+++ b/browser/main/SideNav/index.js
@@ -13,6 +13,7 @@ import StorageList from 'browser/components/StorageList'
import NavToggleButton from 'browser/components/NavToggleButton'
import EventEmitter from 'browser/main/lib/eventEmitter'
import PreferenceButton from './PreferenceButton'
+import SearchButton from './SearchButton'
import ListButton from './ListButton'
import TagButton from './TagButton'
import {SortableContainer} from 'react-sortable-hoc'
@@ -36,21 +37,26 @@ class SideNav extends React.Component {
show: false,
color: null,
tagName: null,
- targetRect: null
+ targetRect: null,
+ showSearch: false,
+ searchText: ''
}
}
this.dismissColorPicker = this.dismissColorPicker.bind(this)
this.handleColorPickerConfirm = this.handleColorPickerConfirm.bind(this)
this.handleColorPickerReset = this.handleColorPickerReset.bind(this)
+ this.handleSearchButtonClick = this.handleSearchButtonClick.bind(this)
+ this.handleSearchInputChange = this.handleSearchInputChange.bind(this)
+ this.handleSearchInputClear = this.handleSearchInputClear.bind(this)
}
componentDidMount () {
- EventEmitter.on('side:preferences', this.handleMenuButtonClick)
+ EventEmitter.on('side:preferences', this.handlePreferenceButtonClick)
}
componentWillUnmount () {
- EventEmitter.off('side:preferences', this.handleMenuButtonClick)
+ EventEmitter.off('side:preferences', this.handlePreferenceButtonClick)
}
deleteTag (tag) {
@@ -99,10 +105,30 @@ class SideNav extends React.Component {
}
}
- handleMenuButtonClick (e) {
+ handlePreferenceButtonClick (e) {
openModal(PreferencesModal)
}
+ handleSearchButtonClick (e) {
+ const { showSearch } = this.state
+ this.setState({
+ showSearch: !showSearch,
+ searchText: ''
+ })
+ }
+
+ handleSearchInputClear (e) {
+ this.setState({
+ searchText: ''
+ })
+ }
+
+ handleSearchInputChange (e) {
+ this.setState({
+ searchText: e.target.value
+ })
+ }
+
handleHomeButtonClick (e) {
const { router } = this.context
router.push('/home')
@@ -181,12 +207,19 @@ class SideNav extends React.Component {
handleToggleButtonClick (e) {
const { dispatch, config } = this.props
+ const { showSearch, searchText } = this.state
ConfigManager.set({isSideNavFolded: !config.isSideNavFolded})
dispatch({
type: 'SET_IS_SIDENAV_FOLDED',
isFolded: !config.isSideNavFolded
})
+
+ if (showSearch && searchText.length === 0) {
+ this.setState({
+ showSearch: false
+ })
+ }
}
handleTrashedButtonClick (e) {
@@ -215,8 +248,9 @@ class SideNav extends React.Component {
}
}
- SideNavComponent (isFolded, storageList) {
- const { location, data, config } = this.props
+ SideNavComponent (isFolded) {
+ const { location, data, config, dispatch } = this.props
+ const { showSearch, searchText } = this.state
const isHomeActive = !!location.pathname.match(/^\/home$/)
const isStarredActive = !!location.pathname.match(/^\/starred$/)
@@ -226,6 +260,28 @@ class SideNav extends React.Component {
// TagsMode is not selected
if (!location.pathname.match('/tags') && !location.pathname.match('/alltags')) {
+ let storageMap = data.storageMap
+ if (showSearch && searchText.length > 0) {
+ storageMap = storageMap.map((storage) => {
+ const folders = storage.folders.filter(folder => folder.name.toLowerCase().indexOf(searchText.toLowerCase()) !== -1)
+ return Object.assign({}, storage, { folders })
+ })
+ }
+
+ const storageList = storageMap.map((storage, key) => {
+ const SortableStorageItem = SortableContainer(StorageItem)
+ return