diff options
-rw-r--r-- | webapp/components/rhs_header_post.jsx | 101 | ||||
-rw-r--r-- | webapp/components/rhs_thread.jsx | 6 | ||||
-rw-r--r-- | webapp/components/search_results.jsx | 11 | ||||
-rw-r--r-- | webapp/components/search_results_header.jsx | 87 | ||||
-rw-r--r-- | webapp/components/search_results_item.jsx | 13 | ||||
-rw-r--r-- | webapp/components/sidebar_right.jsx | 26 | ||||
-rw-r--r-- | webapp/i18n/en.json | 4 | ||||
-rw-r--r-- | webapp/sass/components/_module.scss | 1 | ||||
-rw-r--r-- | webapp/sass/components/_popover.scss | 2 | ||||
-rw-r--r-- | webapp/sass/layout/_headers.scss | 11 | ||||
-rw-r--r-- | webapp/sass/layout/_navigation.scss | 1 | ||||
-rw-r--r-- | webapp/sass/layout/_sidebar-right.scss | 54 | ||||
-rw-r--r-- | webapp/sass/responsive/_mobile.scss | 23 | ||||
-rw-r--r-- | webapp/sass/responsive/_tablet.scss | 29 | ||||
-rw-r--r-- | webapp/utils/utils.jsx | 3 |
15 files changed, 328 insertions, 44 deletions
diff --git a/webapp/components/rhs_header_post.jsx b/webapp/components/rhs_header_post.jsx index 6e0d9276e..8e54016fb 100644 --- a/webapp/components/rhs_header_post.jsx +++ b/webapp/components/rhs_header_post.jsx @@ -3,6 +3,7 @@ import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import Constants from 'utils/constants.jsx'; +import {Tooltip, OverlayTrigger} from 'react-bootstrap'; import * as GlobalActions from 'actions/global_actions.jsx'; import {FormattedMessage} from 'react-intl'; @@ -16,6 +17,7 @@ export default class RhsHeaderPost extends React.Component { super(props); this.handleClose = this.handleClose.bind(this); + this.toggleSize = this.toggleSize.bind(this); this.handleBack = this.handleBack.bind(this); this.state = {}; @@ -23,6 +25,11 @@ export default class RhsHeaderPost extends React.Component { handleClose(e) { e.preventDefault(); GlobalActions.emitCloseRightHandSide(); + this.props.shrink(); + } + toggleSize(e) { + e.preventDefault(); + this.props.toggleSize(); } handleBack(e) { e.preventDefault(); @@ -41,6 +48,42 @@ export default class RhsHeaderPost extends React.Component { } render() { let back; + const closeSidebarTooltip = ( + <Tooltip id='closeSidebarTooltip'> + <FormattedMessage + id='rhs_header.closeTooltip' + defaultMessage='Close Sidebar' + /> + </Tooltip> + ); + + const backToResultsTooltip = ( + <Tooltip id='backToResultsTooltip'> + <FormattedMessage + id='rhs_header.backToResultsTooltip' + defaultMessage='Back to Search Results' + /> + </Tooltip> + ); + + const expandSidebarTooltip = ( + <Tooltip id='expandSidebarTooltip'> + <FormattedMessage + id='rhs_header.expandTooltip' + defaultMessage='Expand Sidebar' + /> + </Tooltip> + ); + + const shrinkSidebarTooltip = ( + <Tooltip id='shrinkSidebarTooltip'> + <FormattedMessage + id='rhs_header.expandTooltip' + defaultMessage='Shrink Sidebar' + /> + </Tooltip> + ); + if (this.props.fromSearch) { back = ( <a @@ -48,7 +91,13 @@ export default class RhsHeaderPost extends React.Component { onClick={this.handleBack} className='sidebar--right__back' > - <i className='fa fa-chevron-left'></i> + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={backToResultsTooltip} + > + <i className='fa fa-angle-left'></i> + </OverlayTrigger> </a> ); } @@ -62,14 +111,44 @@ export default class RhsHeaderPost extends React.Component { defaultMessage='Message Details' /> </span> - <button - type='button' - className='sidebar--right__close' - aria-label='Close' - onClick={this.handleClose} - > - <i className='fa fa-sign-out'/> - </button> + <div className='pull-right'> + <button + type='button' + className='sidebar--right__expand' + aria-label='Expand' + onClick={this.toggleSize} + > + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={expandSidebarTooltip} + > + <i className='fa fa-expand'/> + </OverlayTrigger> + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={shrinkSidebarTooltip} + > + <i className='fa fa-compress'/> + </OverlayTrigger> + </button> + <button + type='button' + className='sidebar--right__close' + aria-label='Close' + onClick={this.handleClose} + > + + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={closeSidebarTooltip} + > + <i className='fa fa-sign-out'/> + </OverlayTrigger> + </button> + </div> </div> ); } @@ -81,5 +160,7 @@ RhsHeaderPost.defaultProps = { }; RhsHeaderPost.propTypes = { isMentionSearch: React.PropTypes.bool, - fromSearch: React.PropTypes.string + fromSearch: React.PropTypes.string, + toggleSize: React.PropTypes.function, + shrink: React.PropTypes.function }; diff --git a/webapp/components/rhs_thread.jsx b/webapp/components/rhs_thread.jsx index 914a697a5..9922e3e1f 100644 --- a/webapp/components/rhs_thread.jsx +++ b/webapp/components/rhs_thread.jsx @@ -230,6 +230,8 @@ export default class RhsThread extends React.Component { <RhsHeaderPost fromSearch={this.props.fromSearch} isMentionSearch={this.props.isMentionSearch} + toggleSize={this.props.toggleSize} + shrink={this.props.shrink} /> <Scrollbars autoHide={true} @@ -293,5 +295,7 @@ RhsThread.propTypes = { fromSearch: React.PropTypes.string, isMentionSearch: React.PropTypes.bool, currentUser: React.PropTypes.object.isRequired, - useMilitaryTime: React.PropTypes.bool.isRequired + useMilitaryTime: React.PropTypes.bool.isRequired, + toggleSize: React.PropTypes.function, + shrink: React.PropTypes.function }; diff --git a/webapp/components/search_results.jsx b/webapp/components/search_results.jsx index ec1307353..6431ff2c2 100644 --- a/webapp/components/search_results.jsx +++ b/webapp/components/search_results.jsx @@ -171,6 +171,7 @@ export default class SearchResults extends React.Component { term={searchTerm} isMentionSearch={this.props.isMentionSearch} useMilitaryTime={this.props.useMilitaryTime} + shrink={this.props.shrink} /> ); }, this); @@ -180,7 +181,11 @@ export default class SearchResults extends React.Component { <div className='sidebar--right__content'> <div className='search-bar__container sidebar--right__search-header'>{searchForm}</div> <div className='sidebar-right__body'> - <SearchResultsHeader isMentionSearch={this.props.isMentionSearch}/> + <SearchResultsHeader + isMentionSearch={this.props.isMentionSearch} + toggleSize={this.props.toggleSize} + shrink={this.props.shrink} + /> <div id='search-items-container' className='search-items-container' @@ -195,5 +200,7 @@ export default class SearchResults extends React.Component { SearchResults.propTypes = { isMentionSearch: React.PropTypes.bool, - useMilitaryTime: React.PropTypes.bool.isRequired + useMilitaryTime: React.PropTypes.bool.isRequired, + toggleSize: React.PropTypes.function, + shrink: React.PropTypes.function }; diff --git a/webapp/components/search_results_header.jsx b/webapp/components/search_results_header.jsx index e9fc2c144..7cb072b70 100644 --- a/webapp/components/search_results_header.jsx +++ b/webapp/components/search_results_header.jsx @@ -3,6 +3,7 @@ import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import Constants from 'utils/constants.jsx'; +import {Tooltip, OverlayTrigger} from 'react-bootstrap'; import {FormattedMessage} from 'react-intl'; @@ -15,6 +16,7 @@ export default class SearchResultsHeader extends React.Component { super(props); this.handleClose = this.handleClose.bind(this); + this.toggleSize = this.toggleSize.bind(this); } handleClose(e) { @@ -36,6 +38,13 @@ export default class SearchResultsHeader extends React.Component { type: ActionTypes.RECEIVED_POST_SELECTED, postId: null }); + + this.props.shrink(); + } + + toggleSize(e) { + e.preventDefault(); + this.props.toggleSize(); } render() { @@ -46,6 +55,33 @@ export default class SearchResultsHeader extends React.Component { /> ); + const closeSidebarTooltip = ( + <Tooltip id='closeSidebarTooltip'> + <FormattedMessage + id='rhs_header.closeTooltip' + defaultMessage='Close Sidebar' + /> + </Tooltip> + ); + + const expandSidebarTooltip = ( + <Tooltip id='expandSidebarTooltip'> + <FormattedMessage + id='rhs_header.expandTooltip' + defaultMessage='Expand Sidebar' + /> + </Tooltip> + ); + + const shrinkSidebarTooltip = ( + <Tooltip id='shrinkSidebarTooltip'> + <FormattedMessage + id='rhs_header.expandTooltip' + defaultMessage='Shrink Sidebar' + /> + </Tooltip> + ); + if (this.props.isMentionSearch) { title = ( <FormattedMessage @@ -58,20 +94,51 @@ export default class SearchResultsHeader extends React.Component { return ( <div className='sidebar--right__header'> <span className='sidebar--right__title'>{title}</span> - <button - type='button' - className='sidebar--right__close' - aria-label='Close' - title='Close' - onClick={this.handleClose} - > - <i className='fa fa-sign-out'/> - </button> + <div className='pull-right'> + <button + type='button' + className='sidebar--right__expand' + aria-label='Expand' + onClick={this.toggleSize} + > + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={expandSidebarTooltip} + > + <i className='fa fa-expand'/> + </OverlayTrigger> + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={shrinkSidebarTooltip} + > + <i className='fa fa-compress'/> + </OverlayTrigger> + </button> + <button + type='button' + className='sidebar--right__close' + aria-label='Close' + title='Close' + onClick={this.handleClose} + > + <OverlayTrigger + delayShow={Constants.OVERLAY_TIME_DELAY} + placement='top' + overlay={closeSidebarTooltip} + > + <i className='fa fa-sign-out'/> + </OverlayTrigger> + </button> + </div> </div> ); } } SearchResultsHeader.propTypes = { - isMentionSearch: React.PropTypes.bool + isMentionSearch: React.PropTypes.bool, + toggleSize: React.PropTypes.function, + shrink: React.PropTypes.function }; diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx index 2f453bc84..217cd5568 100644 --- a/webapp/components/search_results_item.jsx +++ b/webapp/components/search_results_item.jsx @@ -23,10 +23,17 @@ export default class SearchResultsItem extends React.Component { super(props); this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this); + this.shrinkSidebar = this.shrinkSidebar.bind(this); } hideSidebar() { - $('.inner-wrap, .sidebar--right').removeClass('move--left'); + $('.sidebar--right').removeClass('move--left'); + } + + shrinkSidebar() { + setTimeout(() => { + this.props.shrink(); + }); } handleFocusRHSClick(e) { @@ -143,6 +150,7 @@ export default class SearchResultsItem extends React.Component { this.hideSidebar(); } + this.shrinkSidebar(); browserHistory.push('/' + window.location.pathname.split('/')[1] + '/pl/' + post.id); } } @@ -187,5 +195,6 @@ SearchResultsItem.propTypes = { channel: React.PropTypes.object, isMentionSearch: React.PropTypes.bool, term: React.PropTypes.string, - useMilitaryTime: React.PropTypes.bool.isRequired + useMilitaryTime: React.PropTypes.bool.isRequired, + shrink: React.PropTypes.function }; diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx index 3a2060bf2..7cdb894cc 100644 --- a/webapp/components/sidebar_right.jsx +++ b/webapp/components/sidebar_right.jsx @@ -25,6 +25,8 @@ export default class SidebarRight extends React.Component { this.onSearchChange = this.onSearchChange.bind(this); this.onUserChange = this.onUserChange.bind(this); this.onShowSearch = this.onShowSearch.bind(this); + this.onShrink = this.onShrink.bind(this); + this.toggleSize = this.toggleSize.bind(this); this.doStrangeThings = this.doStrangeThings.bind(this); @@ -32,6 +34,7 @@ export default class SidebarRight extends React.Component { searchVisible: SearchStore.getSearchResults() !== null, isMentionSearch: SearchStore.getIsMentionSearch(), postRightVisible: !!PostStore.getSelectedPost(), + expanded: false, fromSearch: false, currentUser: UserStore.getCurrentUser(), useMilitaryTime: PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, Constants.Preferences.USE_MILITARY_TIME, false) @@ -110,6 +113,10 @@ export default class SidebarRight extends React.Component { }); } + onShrink() { + this.setState({expanded: false}); + } + onSearchChange() { this.setState({ searchVisible: SearchStore.getSearchResults() !== null, @@ -131,14 +138,25 @@ export default class SidebarRight extends React.Component { } } + toggleSize() { + this.setState({expanded: !this.state.expanded}); + } + render() { let content = null; + let expandedClass = ''; + + if (this.state.expanded) { + expandedClass = 'sidebar--right--expanded'; + } if (this.state.searchVisible) { content = ( <SearchResults isMentionSearch={this.state.isMentionSearch} useMilitaryTime={this.state.useMilitaryTime} + toggleSize={this.toggleSize} + shrink={this.onShrink} /> ); } else if (this.state.postRightVisible) { @@ -148,15 +166,21 @@ export default class SidebarRight extends React.Component { isMentionSearch={this.state.isMentionSearch} currentUser={this.state.currentUser} useMilitaryTime={this.state.useMilitaryTime} + toggleSize={this.toggleSize} + shrink={this.onShrink} /> ); } return ( <div - className='sidebar--right' + className={'sidebar--right ' + expandedClass} id='sidebar-right' > + <div + onClick={this.onShrink} + className='sidebar--right__bg' + /> <div className='sidebar-right-container'> {content} </div> diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index a632943cd..f38e53993 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1177,6 +1177,10 @@ "rhs_comment.edit": "Edit", "rhs_comment.permalink": "Permalink", "rhs_header.details": "Message Details", + "rhs_header.closeSidebarTooltip": "Close Sidebar", + "rhs_header.backToResultsTooltip": "Back to Search Results", + "rhs_header.expandSidebarTooltip": "Expand Sidebar", + "rhs_header.shrinkSidebarTooltip": "Shrink Sidebar", "rhs_root.del": "Delete", "rhs_root.direct": "Direct Message", "rhs_root.edit": "Edit", diff --git a/webapp/sass/components/_module.scss b/webapp/sass/components/_module.scss index e74404d9c..8c2c575c2 100644 --- a/webapp/sass/components/_module.scss +++ b/webapp/sass/components/_module.scss @@ -14,6 +14,7 @@ @import 'save-button'; @import 'scrollbar'; @import 'search'; +@import 'status-icon'; @import 'suggestion-list'; @import 'tooltip'; @import 'tutorial'; diff --git a/webapp/sass/components/_popover.scss b/webapp/sass/components/_popover.scss index 7526fcb5a..d1e14ec72 100644 --- a/webapp/sass/components/_popover.scss +++ b/webapp/sass/components/_popover.scss @@ -66,7 +66,7 @@ .search-help-popover { @include single-transition(opacity, .3s, ease-in); font-size: em(13px); - max-width: none; + max-width: 350px; top: 36px; visibility: hidden; width: 100%; diff --git a/webapp/sass/layout/_headers.scss b/webapp/sass/layout/_headers.scss index 2382a39e4..cc9f0f713 100644 --- a/webapp/sass/layout/_headers.scss +++ b/webapp/sass/layout/_headers.scss @@ -143,9 +143,16 @@ &.popover { white-space: normal; } - } - @import "../components/status-icon"; + .status { + width: 18px; + + svg { + max-height: 20px; + width: 16px; + } + } + } } .channel-intro { diff --git a/webapp/sass/layout/_navigation.scss b/webapp/sass/layout/_navigation.scss index 70b9eb133..50d144b9c 100644 --- a/webapp/sass/layout/_navigation.scss +++ b/webapp/sass/layout/_navigation.scss @@ -72,6 +72,7 @@ color: $white; display: inline-block; font-weight: 600; + line-height: 47px; margin-right: 5px; max-width: calc(100% - 200px); overflow: hidden; diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss index 00e183254..d98474a7f 100644 --- a/webapp/sass/layout/_sidebar-right.scss +++ b/webapp/sass/layout/_sidebar-right.scss @@ -8,6 +8,18 @@ position: fixed; right: 0; width: 400px; + z-index: 5; + + .sidebar--right__bg { + @include single-transition(background-color, .5s, ease); + background-color: alpha-color($black, 0); + height: 100%; + left: -100%; + position: absolute; + top: 0; + visibility: hidden; + width: 300%; + } .post-body { img { @@ -46,17 +58,29 @@ } .sidebar--right__back { - @include opacity(.8); + @include single-transition(all, .2s, ease-in); + @include opacity(.5); color: inherit; display: inline-block; - font-size: 13px; + font-size: 26px; margin: 0 0 0 -14px; text-align: center; + vertical-align: top; width: 30px; + + &:hover, + &:active { + color: inherit; + opacity: .8; + } + + i { + position: relative; + top: -2px; + } } .sidebar-right__body { - @include border-radius(2px 0 0 0); @include display-flex; @include flex(1 1 auto); @include flex-direction(column); @@ -79,18 +103,22 @@ word-break: break-word; } + .sidebar--right__buttons { + float: right; + } + .sidebar--right__close { @include single-transition(all, .2s, ease-in); background: none; border: none; - float: right; - font-size: 22px; + font-size: 20px; height: 22px; line-height: 0; margin: 11px 0 0; opacity: .5; outline: none; - width: 22px; + padding: 0; + width: 30px; &:hover, &:active { @@ -99,8 +127,20 @@ i { position: relative; + } + } + + .sidebar--right__expand { + @extend .sidebar--right__close; + font-size: 17px; + + i { top: -2px; } + + .fa-compress { + display: none; + } } .sidebar--right__header { @@ -110,7 +150,7 @@ font-size: 1em; height: 44px; line-height: 44px; - padding: 0 1em; + padding: 0 5px 0 15px; text-transform: uppercase; } diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss index 78bd8580d..884c69d74 100644 --- a/webapp/sass/responsive/_mobile.scss +++ b/webapp/sass/responsive/_mobile.scss @@ -314,15 +314,15 @@ } } - .row--invite { - .col-sm-6 { - &:first-child { - padding-right: 15px; + .app__body { + .row--invite { + .col-sm-6 { + &:first-child { + padding-right: 15px; + } } } - } - .app__body { .modal { .info__label { padding-bottom: 5px; @@ -590,8 +590,17 @@ .navbar-brand { white-space: nowrap; + } + + .status { + margin: 0 5px 0 3px; + top: 2px; + width: 16px; - @import "../components/status-icon"; + svg { + max-height: 20px; + width: 16px; + } } } } diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss index 44a7be2ac..69443aafc 100644 --- a/webapp/sass/responsive/_tablet.scss +++ b/webapp/sass/responsive/_tablet.scss @@ -75,6 +75,34 @@ &.move--left { @include translateX(0); } + + &.sidebar--right--expanded { + width: calc(100% - 280px); + + .sidebar--right__bg { + background-color: alpha-color($black, .4); + visibility: visible; + } + + .search-bar__container { + padding-left: 10px; + } + + .sidebar-right-container { + position: relative; + z-index: 5; + } + + .sidebar--right__expand { + .fa-expand { + display: none; + } + + .fa-compress { + display: inline-block; + } + } + } } .inner-wrap { @@ -90,6 +118,7 @@ .post__link { margin: 4px 0 7px; + vertical-align: bottom; } .post__time { diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx index 88d7616de..2792b144c 100644 --- a/webapp/utils/utils.jsx +++ b/webapp/utils/utils.jsx @@ -598,6 +598,7 @@ export function applyTheme(theme) { changeCss('.app__body .popover.left>.arrow:after', 'border-left-color:' + theme.centerChannelBg, 1); changeCss('.app__body .popover.top>.arrow:after, .app__body .tip-overlay.tip-overlay--chat .arrow', 'border-top-color:' + theme.centerChannelBg, 1); changeCss('@media(min-width: 768px){.app__body .search-bar__container .search__form .search-bar, .app__body .form-control', 'background:' + theme.centerChannelBg, 1); + changeCss('@media(min-width: 768px){.app__body .sidebar--right.sidebar--right--expanded .sidebar-right-container', 'background:' + theme.centerChannelBg, 1); changeCss('.app__body .attachment__content', 'background:' + theme.centerChannelBg, 1); changeCss('body.app__body', 'scrollbar-face-color:' + theme.centerChannelBg, 2); changeCss('body.app__body', 'scrollbar-track-color:' + theme.centerChannelBg, 2); @@ -607,7 +608,7 @@ export function applyTheme(theme) { if (theme.centerChannelColor) { changeCss('.app__body .post-list__arrows', 'fill:' + changeOpacity(theme.centerChannelColor, 0.3), 1); changeCss('.app__body .sidebar--left, .app__body .sidebar--right .sidebar--right__header, .app__body .suggestion-list__content .command', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); - changeCss('.app__body .input-group-addon, .app__body .app__content, .app__body .post-create__container .post-create-body .btn-file, .app__body .post-create__container .post-create-footer .msg-typing, .app__body .suggestion-list__content .command, .app__body .modal .modal-content, .app__body .dropdown-menu, .app__body .popover, .app__body .mentions__name, .app__body .tip-overlay', 'color:' + theme.centerChannelColor, 1); + changeCss('.app__body .input-group-addon, .app__body .app__content, .app__body .post-create__container .post-create-body .btn-file, .app__body .post-create__container .post-create-footer .msg-typing, .app__body .suggestion-list__content .command, .app__body .modal .modal-content, .app__body .dropdown-menu, .app__body .popover, .app__body .mentions__name, .app__body .tip-overlay, .app__body .form-control[disabled], .app__body .form-control[readonly], .app__body fieldset[disabled] .form-control', 'color:' + theme.centerChannelColor, 1); changeCss('.app__body .post .post__link', 'color:' + changeOpacity(theme.centerChannelColor, 0.65), 1); changeCss('.app__body #archive-link-home, .video-div .video-thumbnail__error', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); changeCss('.app__body #post-create', 'color:' + theme.centerChannelColor, 2); |