feat: resize side bar when window is wide enough

This commit is contained in:
EnixCoda 2018-06-12 00:58:56 +08:00
parent 5ac46e0b2a
commit 560a64d768
4 changed files with 319 additions and 205 deletions

View file

@ -1,6 +1,7 @@
import preact from 'preact'
/** @jsx preact.h */
import Grabber from '../assets/icons/octicons/grabber.svg?svgr'
import Octoface from '../assets/icons/octicons/octoface.svg?svgr'
import ChevronDown from '../assets/icons/octicons/chevron-down.svg?svgr'
import TriangleRight from '../assets/icons/octicons/triangle-right.svg?svgr'
@ -21,6 +22,8 @@ import cx from '../utils/cx'
function getSVGIconComponent(type) {
switch (type) {
case 'grabber':
return Grabber
case 'octoface':
return Octoface
case 'chevron-down':

View file

@ -0,0 +1,60 @@
import preact from 'preact'
/** @jsx preact.h */
import Icon from './Icon'
export default class ResizeHandler extends preact.Component {
pointerDown = false
startX = 0
delta = 0
baseSize = this.props.baseSize
subscribeEvents = () => {
window.addEventListener('mousemove', this.onPointerMove)
window.addEventListener('mouseup', this.onPointerUp)
}
unsubscribeEvents = () => {
window.removeEventListener('mousemove', this.onPointerMove)
window.removeEventListener('mouseup', this.onPointerUp)
}
/**
*
* @param {MouseEvent} e
* @memberof ResizeHandler
*/
onPointerDown = e => {
this.pointerDown = true
const { clientX } = e
this.startX = clientX
this.subscribeEvents()
}
onPointerMove = e => {
if (!this.pointerDown) return
const { clientX } = e
const { onResize } = this.props
this.delta = this.startX - clientX
onResize(this.delta + this.baseSize)
}
onPointerUp = () => {
this.pointerDown = false
this.baseSize += this.delta
this.unsubscribeEvents()
}
render() {
const { style } = this.props
return (
<div
className={'gitako-resize-handler'}
onMouseDown={this.onPointerDown}
style={style}
>
<Icon type={'grabber'} className={'grabber-icon'} />
</div>
)
}
}

View file

@ -7,6 +7,7 @@ import FileExplorer from './FileExplorer'
import ToggleShowButton from './ToggleShowButton'
import MetaBar from './MetaBar'
import SettingsBar from './SettingsBar'
import ResizeHandler from './ResizeHandler'
import cx from '../utils/cx'
import DOMHelper, { REPO_TYPE_PRIVATE } from '../utils/DOMHelper'
@ -15,8 +16,12 @@ import storageHelper from '../utils/storageHelper'
import URLHelper from '../utils/URLHelper'
import keyHelper from '../utils/keyHelper'
// initial width of side bar
const baseSize = 260
export default class SideBar extends preact.Component {
state = {
// current width of side bar
size: 260,
// whether Gitako side bar should be shown
shouldShow: false,
// whether show settings pane
@ -127,6 +132,12 @@ export default class SideBar extends preact.Component {
this.setState({ toggleShowSideBarShortcut: shortcut })
}
onResize = size => {
this.setState({
size,
})
}
renderAccessDeniedError() {
return (
<div className={'description'}>
@ -155,6 +166,7 @@ export default class SideBar extends preact.Component {
render() {
const {
size,
shouldShow,
showSettings,
hasAccessToken,
@ -166,16 +178,19 @@ export default class SideBar extends preact.Component {
<Portal into={this.logoContainerElement}>
<ToggleShowButton shouldShow={shouldShow} toggleShowSideBar={this.toggleShowSideBar} />
</Portal>
<div className={'gitako-side-bar'}>
{this.renderContent()}
<SettingsBar
toggleShowSettings={this.toggleShowSettings}
onShortcutChange={this.onShortcutChange}
onHasAccessTokenChange={this.onHasAccessTokenChange}
activated={showSettings}
hasAccessToken={hasAccessToken}
toggleShowSideBarShortcut={toggleShowSideBarShortcut}
/>
<div className={'gitako-position-wrapper'}>
<ResizeHandler onResize={this.onResize} baseSize={baseSize} style={{ right: size }} />
<div className={'gitako-side-bar'} style={{ width: size }}>
{this.renderContent()}
<SettingsBar
toggleShowSettings={this.toggleShowSettings}
onShortcutChange={this.onShortcutChange}
onHasAccessTokenChange={this.onHasAccessTokenChange}
activated={showSettings}
hasAccessToken={hasAccessToken}
toggleShowSideBarShortcut={toggleShowSideBarShortcut}
/>
</div>
</div>
</div>
)

View file

@ -2,16 +2,17 @@
@name: gitako;
@side-bar-width: 260px;
@github-content-width: 1280px;
@content-width: (@side-bar-width + @github-content-width);
@min-screen-width: 1280px;
@github-content-width: 1020px;
@side-bar-base-width: (@min-screen-width - @github-content-width);
@width-with-gitako: (@min-screen-width + @side-bar-base-width);
.with-@{name}-spacing {
margin-left: @side-bar-width;
@media (min-width: @github-content-width) and (max-width: @content-width) {
margin-left: ~'calc(' @content-width ~' - 100vw)';
margin-left: @side-bar-base-width;
@media (min-width: @min-screen-width) and (max-width: @width-with-gitako) {
margin-left: ~'calc(' @width-with-gitako ~' - 100vw)';
}
@media (min-width: @content-width) {
@media (min-width: @width-with-gitako) {
margin-left: 0;
}
}
@ -68,10 +69,11 @@
}
.@{name}-toggle-show-button-wrapper {
@animation-duration: 0.8s;
@animation-duration: 0.5s;
position: fixed;
top: 5px;
left: 0;
transform: translate((@side-bar-base-width - 30px));
z-index: 2;
display: inline-flex;
justify-content: center;
@ -80,20 +82,23 @@
width: 30px;
height: 30px;
will-change: transform;
transform: translateX(225px);
transition: all @animation-duration ease;
border: 1px solid transparent;
@media screen and (min-width: @content-width) {
transform: translateX(~'calc((100vw - ' @content-width ~') / 2 + ' 225px ~')');
@media screen and (max-width: @width-with-gitako) {
transition: all @animation-duration ease;
}
@media screen and (min-width: @width-with-gitako) {
transition: border-color, border-radius, background @animation-duration ease;
transform: translate(~'calc(50vw - (' @github-content-width ~') / 2 - 30px)');
}
&.collapsed {
border-color: #999999;
background: #f5f5f5;
border-radius: 3px;
background: #f5f5f5;
@media screen and (max-width: @content-width) {
transform: translateX(5px);
@media screen and (max-width: @width-with-gitako) {
transform: translate(5px);
}
.action-icon {
@ -110,198 +115,229 @@
}
.@{name} {
.@{name}-side-bar {
.@{name}-position-wrapper {
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
width: @side-bar-width;
height: 100vh;
z-index: 2;
background: #fafbfc;
border-right: 1px solid #e1e4e8;
overflow: hidden;
min-width: @side-bar-base-width;
@media screen and (min-width: @min-screen-width) {
width: ~'calc((100vw - ' @github-content-width ~') / 2)';
}
@media screen and (min-width: @content-width) {
.@{name}-resize-handler {
@resize-handler-width: 16px;
@side-bar-and-handler-width: (@min-screen-width + @resize-handler-width);
position: absolute;
top: 0;
display: none;
width: @resize-handler-width;
height: 100vh;
background: #fafbfc;
cursor: ew-resize;
user-select: none;
border-left: 1px solid #e1e4e8;
left: ~'calc((100vw - ' @content-width ~') / 2)';
}
&.hidden {
.hidden;
}
.octicon {
transition: 0.3s ease;
color: rgba(3, 47, 98, 0.55);
vertical-align: initial;
}
.octicon-wrapper {
display: inline-block;
width: 16px;
height: 16px;
text-align: center;
vertical-align: middle;
}
.octicon-color {
color: rgba(3, 47, 98, 0.55);
}
.@{name}-side-bar-content {
display: flex;
flex: 1;
flex-direction: column;
.meta-bar {
position: relative;
padding: 10px;
padding-right: 30px;
font-size: 13px;
line-height: 20px;
color: #586069;
background-color: #f1f8ff;
border-bottom: 1px solid #c8e1ff;
a {
// fix a weird bug:
// when gitako failed loading repo, cursor hovering <a> in meta bar will be 'text'
cursor: pointer;
}
.repo-name {
font-weight: bolder;
}
}
.description {
padding: 4px 10px;
}
.file-explorer {
width: 100%;
height: 100%;
outline: none;
@media screen and (min-width: @min-screen-width) {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
&.freeze {
filter: blur(1.5px) opacity(0.6) grayscale(0.9);
pointer-events: none;
}
/* search input */
.search-input-wrapper {
input[type='text'].form-control {
box-shadow: none;
width: 100%;
}
}
.no-results {
padding: 0px 10px;
color: #666;
}
.files {
flex: 1;
overflow: auto;
}
.node-item-row {
background: #fff;
&:hover {
background: #f6f8fa;
}
&.focused {
background: #f0f0f6;
}
.node-item {
word-wrap: normal;
word-break: break-all;
margin: 0;
color: #0366d6;
line-height: 20px;
padding: 6px 0;
cursor: pointer;
border-top: 1px solid #eaecef;
transition: all 0.5s ease;
// folder icon rotate when expand
&.expanded .octicon.octicon-triangle-right {
transform: rotate(90deg);
}
.node-item-name {
padding-left: 6px;
vertical-align: middle;
}
.node-item:hover .node-item-name {
text-decoration: underline;
}
}
}
}
}
.@{name}-settings-bar {
border-top: 1px solid #eaecef;
&-content {
padding: 0 10px;
&-section {
padding-bottom: 10px;
}
}
.access-token {
border-bottom: none; // prevent overwrite by github style
.hint {
color: #6a737d;
}
}
.access-token-input-control {
display: flex;
margin-top: 8px;
.access-token-input {
flex: 1;
box-shadow: none;
&:disabled {
cursor: not-allowed;
}
}
}
.toggle-shortcut {
.hint {
color: #6a737d;
}
}
.toggle-shortcut-input-control {
display: flex;
margin-top: 8px;
.toggle-shortcut-input {
flex: 1;
box-shadow: none;
}
}
.placeholder-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 10px;
}
.show-settings-icon {
width: 20px;
height: 20px;
cursor: pointer;
.grabber-icon {
transform: rotate(90deg);
width: 12px;
}
}
.@{name}-side-bar {
position: absolute;
right: 0;
width: @side-bar-base-width;
max-width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background: #fafbfc;
border-right: 1px solid #e1e4e8;
overflow: hidden;
will-change: transform;
border-left: 1px solid #e1e4e8;
&.hidden {
.hidden;
}
.octicon {
transition: 0.3s ease;
color: rgba(3, 47, 98, 0.55);
vertical-align: initial;
}
.octicon-wrapper {
display: inline-block;
width: 16px;
height: 16px;
text-align: center;
vertical-align: middle;
}
.octicon-color {
color: rgba(3, 47, 98, 0.55);
}
.@{name}-side-bar-content {
display: flex;
flex: 1;
flex-direction: column;
.meta-bar {
position: relative;
padding: 10px;
padding-right: 30px;
font-size: 13px;
line-height: 20px;
color: #586069;
background-color: #f1f8ff;
border-bottom: 1px solid #c8e1ff;
a {
// fix a weird bug:
// when gitako failed loading repo, cursor hovering <a> in meta bar will be 'text'
cursor: pointer;
}
.repo-name {
font-weight: bolder;
}
}
.hide-settings-icon {
width: 15px;
height: 24px;
cursor: pointer;
.description {
padding: 4px 10px;
}
.file-explorer {
width: 100%;
height: 100%;
outline: none;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
&.freeze {
filter: blur(1.5px) opacity(0.6) grayscale(0.9);
pointer-events: none;
}
/* search input */
.search-input-wrapper {
input[type='text'].form-control {
box-shadow: none;
width: 100%;
}
}
.no-results {
padding: 0px 10px;
color: #666;
}
.files {
flex: 1;
overflow: auto;
}
.node-item-row {
background: #fff;
&:hover {
background: #f6f8fa;
}
&.focused {
background: #f0f0f6;
}
.node-item {
word-wrap: normal;
word-break: break-all;
margin: 0;
color: #0366d6;
line-height: 20px;
padding: 6px 0;
cursor: pointer;
border-top: 1px solid #eaecef;
transition: all 0.5s ease;
// folder icon rotate when expand
&.expanded .octicon.octicon-triangle-right {
transform: rotate(90deg);
}
.node-item-name {
padding-left: 6px;
vertical-align: middle;
}
.node-item:hover .node-item-name {
text-decoration: underline;
}
}
}
}
}
.@{name}-settings-bar {
border-top: 1px solid #eaecef;
&-content {
padding: 0 10px;
&-section {
padding-bottom: 10px;
}
}
.access-token {
border-bottom: none; // prevent overwrite by github style
.hint {
color: #6a737d;
}
}
.access-token-input-control {
display: flex;
margin-top: 8px;
.access-token-input {
flex: 1;
box-shadow: none;
&:disabled {
cursor: not-allowed;
}
}
}
.toggle-shortcut {
.hint {
color: #6a737d;
}
}
.toggle-shortcut-input-control {
display: flex;
margin-top: 8px;
.toggle-shortcut-input {
flex: 1;
box-shadow: none;
}
}
.placeholder-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 10px;
.show-settings-icon {
width: 20px;
height: 20px;
cursor: pointer;
}
.hide-settings-icon {
width: 15px;
height: 24px;
cursor: pointer;
}
}
}
}