From f57bfeae69dad776ded64dc3ad7cad8278606d5d Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 19 Jan 2017 14:33:45 -0800 Subject: [PATCH 01/14] again --- lib/git-shell-out-strategy.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/git-shell-out-strategy.js b/lib/git-shell-out-strategy.js index 5457e5f05b..50c2788298 100644 --- a/lib/git-shell-out-strategy.js +++ b/lib/git-shell-out-strategy.js @@ -57,6 +57,7 @@ export default class GitShellOutStrategy { processCallback: child => { child.on('error', err => { console.error('Error executing: ' + formattedArgs); + console.error(err.stack); }); child.stdin.on('error', err => { From a8f1d09ca540c81ae24a9aa202f0c8e832d88f8a Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 19 Jan 2017 16:47:10 -0800 Subject: [PATCH 02/14] Implement those tabs :sparkles: --- lib/controllers/git-controller.js | 55 +++++++++++------- lib/views/tabs.js | 97 +++++++++++++++++++++++++++++++ styles/git-panel.less | 2 +- styles/tabs.less | 65 +++++++++++++++++++++ 4 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 lib/views/tabs.js create mode 100644 styles/tabs.less diff --git a/lib/controllers/git-controller.js b/lib/controllers/git-controller.js index a47276a74e..0c3ab4247e 100644 --- a/lib/controllers/git-controller.js +++ b/lib/controllers/git-controller.js @@ -10,6 +10,7 @@ import StatusBar from '../views/status-bar'; import Panel from '../views/panel'; import PaneItem from '../views/pane-item'; import Resizer from '../views/resizer'; +import Tabs from '../views/tabs'; import Commands, {Command} from '../views/commands'; import FilePatchController from './file-patch-controller'; import GitPanelController from './git-panel-controller'; @@ -51,6 +52,7 @@ export default class GitController extends React.Component { amending: false, gitPanelActive: !!props.savedState.gitPanelActive, panelSize: props.savedState.panelSize || 400, + activeTab: 0, }; this.repositoryStateRegistry = new ModelStateRegistry(GitController, { @@ -123,27 +125,34 @@ export default class GitController extends React.Component { size={this.state.panelSize} onChange={this.handlePanelResize} className="github-PanelResizer"> - { this.gitPanelController = c; }} - className="github-PanelEtchWrapper" - reattachDomNode={false}> - - + + + { this.gitPanelController = c; }} + className="github-PanelEtchWrapper" + reattachDomNode={false}> + + + + + Hello from Hub + + ); @@ -315,4 +324,8 @@ export default class GitController extends React.Component { return this.props.repository.discardWorkDirChangesForPaths(filePaths); } + @autobind + handleChangeTab(activeTab) { + this.setState({activeTab}); + } } diff --git a/lib/views/tabs.js b/lib/views/tabs.js new file mode 100644 index 0000000000..0823bb0a49 --- /dev/null +++ b/lib/views/tabs.js @@ -0,0 +1,97 @@ +import React from 'react'; +import cx from 'classnames'; +import {autobind} from 'core-decorators'; + +function getClasses(staticClasses, active) { + return cx(...staticClasses, { + inactive: !active, + active, + }); +} + +class TabsNavigationItem extends React.Component { + static propTypes = { + title: React.PropTypes.string, + tabIndex: React.PropTypes.number.isRequired, + active: React.PropTypes.bool, + onClick: React.PropTypes.func, + } + + render() { + const classes = getClasses(['github-Tabs-NavigationItem'], this.props.active); + return ( +
+ {this.props.title} +
+ ); + } + + @autobind + handleClick() { + this.props.onClick(this.props.tabIndex); + } +} + +class Tabs extends React.Component { + static propTypes = { + className: React.PropTypes.string, + activeIndex: React.PropTypes.number.isRequired, + children: React.PropTypes.node, + onChange: React.PropTypes.func, + } + + static defaultProps = { + className: '', + onChange: () => {}, + } + + render() { + const children = React.Children.toArray(this.props.children).filter(v => !!v); + return ( +
+ +
+ {children.map((child, i) => ( + child && React.cloneElement(child, {active: i === this.props.activeIndex}) + ))} +
+
+ ); + } +} + +class Panel extends React.Component { + static propTypes = { + className: React.PropTypes.string, + active: React.PropTypes.bool, + children: React.PropTypes.node, + } + + static defaultProps = { + className: '', + active: false, + } + + render() { + // eslint-disable-next-line no-unused-vars + const {active, children, className, ...others} = this.props; + return ( +
+ {this.props.children} +
+ ); + } +} + +Tabs.Panel = Panel; +export default Tabs; diff --git a/styles/git-panel.less b/styles/git-panel.less index 57e515839e..ed1fc8f5ba 100644 --- a/styles/git-panel.less +++ b/styles/git-panel.less @@ -2,7 +2,7 @@ .github-PanelResizer { // ok, yeah, magic number.. err color - background-color: mix(@base-background-color, @tool-panel-background-color); + // background-color: mix(@base-background-color, @tool-panel-background-color); } .github-PanelEtchWrapper { diff --git a/styles/tabs.less b/styles/tabs.less new file mode 100644 index 0000000000..97973d771d --- /dev/null +++ b/styles/tabs.less @@ -0,0 +1,65 @@ +// General Styles +.github-Tabs { + &-Panel { + &.active { + display: block; + } + + &.inactive { + display: none; + } + } +} + +// App-specific styles +.github-Tabs.sidebar-tabs { + height: 100%; + display: flex; + flex-direction: column; + + .github-Tabs-NavigationContainer { + display: flex; + flex-direction: row; + padding-top: 10px; + } + + &[data-tabs-count="1"] { + .github-Tabs-NavigationContainer { + display: none; + } + } + + .github-Tabs-PanelContainer { + flex: 1; + display: flex; + flex-direction: column; + // background-color: mix(@base-background-color, @tool-panel-background-color); + } + + .github-Tabs-NavigationItem { + flex: 1; + display: flex; + text-align: center; + flex-direction: column; + justify-content: center; + cursor: pointer; + height: 30px; + + &.active { + border: 1px solid @tab-border-color; + border-left: 2px solid @background-color-info; + border-bottom: none; + background: @tab-background-color-active; + } + } + + .github-Tabs-Panel { + flex: 1; + + &.active { + } + + &.inactive { + } + } +} From a055aef892575ef3083a4dfddc2a770e403bff85 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 19 Jan 2017 17:41:08 -0800 Subject: [PATCH 03/14] Only display github panel if `github.githubEnabled` config is true --- lib/controllers/git-controller.js | 10 +++++++--- lib/github-package.js | 6 +++++- lib/index.js | 2 +- lib/views/tabs.js | 4 ++-- test/github-package.test.js | 5 +++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/lib/controllers/git-controller.js b/lib/controllers/git-controller.js index 0c3ab4247e..4a36982f94 100644 --- a/lib/controllers/git-controller.js +++ b/lib/controllers/git-controller.js @@ -32,10 +32,12 @@ export default class GitController extends React.Component { repository: React.PropTypes.object, statusBar: React.PropTypes.object, savedState: React.PropTypes.object, + githubEnabled: React.PropTypes.bool, } static defaultProps = { savedState: {}, + githubEnabled: false, } serialize() { @@ -149,9 +151,11 @@ export default class GitController extends React.Component { /> - - Hello from Hub - + {this.props.githubEnabled && ( + + Hello from Hub + + )} diff --git a/lib/github-package.js b/lib/github-package.js index 60f46e4130..cb93c56659 100644 --- a/lib/github-package.js +++ b/lib/github-package.js @@ -14,11 +14,12 @@ import FilePatchController from './controllers/file-patch-controller'; import GitController from './controllers/git-controller'; export default class GithubPackage { - constructor(workspace, project, commandRegistry, notificationManager) { + constructor(workspace, project, commandRegistry, notificationManager, config) { this.workspace = workspace; this.project = project; this.commandRegistry = commandRegistry; this.notificationManager = notificationManager; + this.config = config; this.repositoriesAndChangeObserversByProjectPath = new Map(); this.activeRepository = null; this.subscriptions = new CompositeDisposable(); @@ -33,6 +34,7 @@ export default class GithubPackage { this.subscriptions.add( this.project.onDidChangePaths(this.didChangeProjectPaths), this.workspace.onDidChangeActivePaneItem(this.didChangeActivePaneItem), + this.config.onDidChange('github.githubEnabled', this.rerender), ); if (state.activeRepositoryPath) { const repository = await this.getRepositoryForWorkdirPath(state.activeRepositoryPath); @@ -51,6 +53,7 @@ export default class GithubPackage { }; } + @autobind rerender() { if (!this.element) { this.element = document.createElement('div'); @@ -69,6 +72,7 @@ export default class GithubPackage { repository={this.getActiveRepository()} statusBar={this.statusBar} savedState={this.savedState.gitController} + githubEnabled={this.config.get('github.githubEnabled')} />, this.element, ); } diff --git a/lib/index.js b/lib/index.js index bdcdc1b900..931ef44f4d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -28,6 +28,6 @@ function startPackage() { var GithubPackage = require('./github-package').default; return new GithubPackage( - atom.workspace, atom.project, atom.commands, atom.notifications, + atom.workspace, atom.project, atom.commands, atom.notifications, atom.config, ); } diff --git a/lib/views/tabs.js b/lib/views/tabs.js index 0823bb0a49..c1d602f825 100644 --- a/lib/views/tabs.js +++ b/lib/views/tabs.js @@ -70,7 +70,7 @@ class Tabs extends React.Component { } } -class Panel extends React.Component { +class TabPanel extends React.Component { static propTypes = { className: React.PropTypes.string, active: React.PropTypes.bool, @@ -93,5 +93,5 @@ class Panel extends React.Component { } } -Tabs.Panel = Panel; +Tabs.Panel = TabPanel; export default Tabs; diff --git a/test/github-package.test.js b/test/github-package.test.js index ff19658ca2..de81425e26 100644 --- a/test/github-package.test.js +++ b/test/github-package.test.js @@ -9,7 +9,7 @@ import {cloneRepository} from './helpers'; import GithubPackage from '../lib/github-package'; describe('GithubPackage', function() { - let atomEnv, workspace, project, commandRegistry, notificationManager, githubPackage; + let atomEnv, workspace, project, commandRegistry, notificationManager, config, githubPackage; beforeEach(function() { atomEnv = global.buildAtomEnvironment(); @@ -17,7 +17,8 @@ describe('GithubPackage', function() { project = atomEnv.project; commandRegistry = atomEnv.commands; notificationManager = atomEnv.notifications; - githubPackage = new GithubPackage(workspace, project, commandRegistry, notificationManager); + config = atomEnv.config; + githubPackage = new GithubPackage(workspace, project, commandRegistry, notificationManager, config); }); afterEach(async function() { From 60a4b771495629c19b6ae3b58febaecf0db02ea1 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Thu, 19 Jan 2017 18:16:40 -0800 Subject: [PATCH 04/14] :art: per @smashwilson --- lib/views/tabs.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/views/tabs.js b/lib/views/tabs.js index c1d602f825..451b56363e 100644 --- a/lib/views/tabs.js +++ b/lib/views/tabs.js @@ -32,7 +32,7 @@ class TabsNavigationItem extends React.Component { } } -class Tabs extends React.Component { +export default class Tabs extends React.Component { static propTypes = { className: React.PropTypes.string, activeIndex: React.PropTypes.number.isRequired, @@ -70,7 +70,7 @@ class Tabs extends React.Component { } } -class TabPanel extends React.Component { +Tabs.Panel = class TabPanel extends React.Component { static propTypes = { className: React.PropTypes.string, active: React.PropTypes.bool, @@ -91,7 +91,4 @@ class TabPanel extends React.Component { ); } -} - -Tabs.Panel = TabPanel; -export default Tabs; +}; From bb8642e4d7e8acda3efd6312b02deec2a4cc6f30 Mon Sep 17 00:00:00 2001 From: simurai Date: Fri, 20 Jan 2017 16:55:46 +0900 Subject: [PATCH 05/14] Style tabs --- styles/git-panel.less | 5 ----- styles/tabs.less | 18 +++++++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/styles/git-panel.less b/styles/git-panel.less index ed1fc8f5ba..d9f75e2d35 100644 --- a/styles/git-panel.less +++ b/styles/git-panel.less @@ -1,10 +1,5 @@ @import "variables"; -.github-PanelResizer { - // ok, yeah, magic number.. err color - // background-color: mix(@base-background-color, @tool-panel-background-color); -} - .github-PanelEtchWrapper { height: 100%; } diff --git a/styles/tabs.less b/styles/tabs.less index 97973d771d..1a63264df4 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -1,3 +1,5 @@ +@import "variables"; + // General Styles .github-Tabs { &-Panel { @@ -20,7 +22,6 @@ .github-Tabs-NavigationContainer { display: flex; flex-direction: row; - padding-top: 10px; } &[data-tabs-count="1"] { @@ -33,7 +34,7 @@ flex: 1; display: flex; flex-direction: column; - // background-color: mix(@base-background-color, @tool-panel-background-color); + background-color: @inset-panel-background-color; } .github-Tabs-NavigationItem { @@ -43,13 +44,16 @@ flex-direction: column; justify-content: center; cursor: pointer; - height: 30px; + height: 36px; // TODO: This is currently matched with the One themes + border-bottom: 1px solid @tab-border-color; + + & + .github-Tabs-NavigationItem { + border-left: 1px solid @tab-border-color; + } &.active { - border: 1px solid @tab-border-color; - border-left: 2px solid @background-color-info; - border-bottom: none; - background: @tab-background-color-active; + border-bottom-color: transparent; + background-color: @inset-panel-background-color; } } From 364b0f65ea802d6717e85f2f1baec48b957c9e62 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 20 Jan 2017 15:34:35 -0800 Subject: [PATCH 06/14] Allow TabPanel title to be a node --- lib/views/tabs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/views/tabs.js b/lib/views/tabs.js index 451b56363e..2497fd7a44 100644 --- a/lib/views/tabs.js +++ b/lib/views/tabs.js @@ -11,7 +11,7 @@ function getClasses(staticClasses, active) { class TabsNavigationItem extends React.Component { static propTypes = { - title: React.PropTypes.string, + title: React.PropTypes.node, tabIndex: React.PropTypes.number.isRequired, active: React.PropTypes.bool, onClick: React.PropTypes.func, From 0bf5a033c595e2aacadeffce1d9dbb56fde84b30 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 20 Jan 2017 15:34:57 -0800 Subject: [PATCH 07/14] Don't copy title prop onto Tab Panel DOM node --- lib/views/tabs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/views/tabs.js b/lib/views/tabs.js index 2497fd7a44..1780c161cd 100644 --- a/lib/views/tabs.js +++ b/lib/views/tabs.js @@ -75,6 +75,7 @@ Tabs.Panel = class TabPanel extends React.Component { className: React.PropTypes.string, active: React.PropTypes.bool, children: React.PropTypes.node, + title: React.PropTypes.node, } static defaultProps = { @@ -84,7 +85,7 @@ Tabs.Panel = class TabPanel extends React.Component { render() { // eslint-disable-next-line no-unused-vars - const {active, children, className, ...others} = this.props; + const {active, children, className, title, ...others} = this.props; return (
{this.props.children} From 39995ed40122f826573f460ba5bc4960dbc1f18c Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 20 Jan 2017 15:35:22 -0800 Subject: [PATCH 08/14] Change Tab conditional rendering to fix linter format --- lib/views/tabs.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/views/tabs.js b/lib/views/tabs.js index 1780c161cd..8153fd60d1 100644 --- a/lib/views/tabs.js +++ b/lib/views/tabs.js @@ -50,19 +50,19 @@ export default class Tabs extends React.Component { return (
- {children.map((child, i) => ( - child && React.cloneElement(child, {active: i === this.props.activeIndex}) + {children.map((child, i) => child && ( + React.cloneElement(child, {active: i === this.props.activeIndex}) ))}
From 8d7d0943bd00f3431ac99f2362d0e957d315f33f Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Fri, 20 Jan 2017 15:36:34 -0800 Subject: [PATCH 09/14] Display tabs navigation as a segmented button group --- styles/tabs.less | 59 +++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/styles/tabs.less b/styles/tabs.less index 1a63264df4..c4ccb79a61 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -22,6 +22,44 @@ .github-Tabs-NavigationContainer { display: flex; flex-direction: row; + padding: 10px; + + .github-Tabs-NavigationItem { + flex: 1; + text-align: center; + cursor: pointer; + background-color: @button-background-color; + color: @text-color; + padding: 5px; + border: 1px solid @button-border-color; + + &.active { + background-color: @button-background-color-selected; + color: @base-background-color; + border-color: @button-background-color-selected; + } + + &:first-child { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + } + + &:first-child:not(:last-child) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + } + + &:last-child { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; + } + + &:last-child:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + } + } &[data-tabs-count="1"] { @@ -34,27 +72,6 @@ flex: 1; display: flex; flex-direction: column; - background-color: @inset-panel-background-color; - } - - .github-Tabs-NavigationItem { - flex: 1; - display: flex; - text-align: center; - flex-direction: column; - justify-content: center; - cursor: pointer; - height: 36px; // TODO: This is currently matched with the One themes - border-bottom: 1px solid @tab-border-color; - - & + .github-Tabs-NavigationItem { - border-left: 1px solid @tab-border-color; - } - - &.active { - border-bottom-color: transparent; - background-color: @inset-panel-background-color; - } } .github-Tabs-Panel { From 99cc35ab44f57f1a9172917f6984a9d7da9e1ceb Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 21 Jan 2017 11:18:36 +0900 Subject: [PATCH 10/14] Add contrast to labels So it works for light and dark themes --- styles/tabs.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/styles/tabs.less b/styles/tabs.less index c4ccb79a61..4a67d34e7c 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -29,13 +29,13 @@ text-align: center; cursor: pointer; background-color: @button-background-color; - color: @text-color; + color: contrast(@button-background-color, hsla(0,0%,0%,.6), hsla(0,0%,100%,.6)); padding: 5px; border: 1px solid @button-border-color; &.active { background-color: @button-background-color-selected; - color: @base-background-color; + color: contrast(@button-background-color-selected, hsla(0,0%,0%,1), hsla(0,0%,100%,1)); border-color: @button-background-color-selected; } From 2dc7fb1bfee50fc95e708be224e93bd468320295 Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 21 Jan 2017 11:25:24 +0900 Subject: [PATCH 11/14] Show border also when active So that the height still looks the same --- styles/tabs.less | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/styles/tabs.less b/styles/tabs.less index 4a67d34e7c..b8d6d040da 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -33,10 +33,13 @@ padding: 5px; border: 1px solid @button-border-color; + & + .github-Tabs-NavigationItem { + border-left: none; + } + &.active { background-color: @button-background-color-selected; color: contrast(@button-background-color-selected, hsla(0,0%,0%,1), hsla(0,0%,100%,1)); - border-color: @button-background-color-selected; } &:first-child { From b978b9cd3b81036a47c39539dcdc300d8d8155da Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 21 Jan 2017 11:29:28 +0900 Subject: [PATCH 12/14] Use variable for corner radius So it matches other stuff like buttons or inputs. Also I think the `:not()` selectors aren't really needed. --- styles/tabs.less | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/styles/tabs.less b/styles/tabs.less index b8d6d040da..c2860e1f44 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -43,23 +43,13 @@ } &:first-child { - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - } - - &:first-child:not(:last-child) { - border-bottom-right-radius: 0; - border-top-right-radius: 0; + border-top-left-radius: @component-border-radius; + border-bottom-left-radius: @component-border-radius; } &:last-child { - border-top-right-radius: 5px; - border-bottom-right-radius: 5px; - } - - &:last-child:not(:first-child) { - border-bottom-left-radius: 0; - border-top-left-radius: 0; + border-top-right-radius: @component-border-radius; + border-bottom-right-radius: @component-border-radius; } } From 3073d62e567fee6f6edc002e1d18313e37cd8011 Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 21 Jan 2017 11:59:45 +0900 Subject: [PATCH 13/14] Use variable for padding So it matches themes --- styles/tabs.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/tabs.less b/styles/tabs.less index c2860e1f44..6b23a860c4 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -22,7 +22,7 @@ .github-Tabs-NavigationContainer { display: flex; flex-direction: row; - padding: 10px; + padding: @component-padding; .github-Tabs-NavigationItem { flex: 1; From c8cb7a3fc54c02347c996083479c1f1501b93ca0 Mon Sep 17 00:00:00 2001 From: simurai Date: Sat, 21 Jan 2017 12:05:16 +0900 Subject: [PATCH 14/14] Add ellipsis In case they overflow, one day. --- styles/tabs.less | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/styles/tabs.less b/styles/tabs.less index 6b23a860c4..d5a311e0a6 100644 --- a/styles/tabs.less +++ b/styles/tabs.less @@ -30,8 +30,11 @@ cursor: pointer; background-color: @button-background-color; color: contrast(@button-background-color, hsla(0,0%,0%,.6), hsla(0,0%,100%,.6)); - padding: 5px; border: 1px solid @button-border-color; + padding: .25em .5em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; & + .github-Tabs-NavigationItem { border-left: none;