From 5c7256ffe5004780d754939b4664df391602c924 Mon Sep 17 00:00:00 2001 From: TakuroOnoda Date: Sun, 18 Oct 2020 18:48:10 +0900 Subject: [PATCH 1/2] Adding Tab Location "left" --- .../src/components/appRoot.component.pug | 206 ++++++++++-------- .../src/components/appRoot.component.scss | 28 ++- .../src/components/tabHeader.component.scss | 5 + .../src/components/settingsTab.component.pug | 7 + .../src/components/settingsTab.component.ts | 2 +- terminus-ssh/package.json | 2 +- .../src/api/baseTerminalTab.component.ts | 2 +- 7 files changed, 162 insertions(+), 90 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 21e018cc..887dfaf6 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -3,99 +3,133 @@ title-bar( [class.inset]='hostApp.platform == Platform.macOS' ) -.content( - [class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' -) - .tab-bar - .inset.background(*ngIf='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"') - .tabs( - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', +.wrap + .tab-bar.vertical( + *ngIf='config.store.appearance.tabsLocation == "left"' + ) + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin"') + .tabs.vertical( + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - ) + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + [class.vertical]='true', + ) - .btn-group.background - .d-flex( - *ngFor='let button of leftToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') + .content( + [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', + [class.with-side-tab]='config.store.appearance.tabsLocation == "left"', + ) + .tab-bar + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin" \ + && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') + .tabs( + *ngIf='config.store.appearance.tabsLocation != "left"' + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - .btn-group.background - .d-flex( - *ngFor='let button of rightToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + ) - button.btn.btn-secondary.btn-tab-bar.btn-update( - *ngIf='updatesAvailable', - title='Update available - Click to install', - (click)='updateApp()', - [fastHtmlBind]='updateIcon' - ) + .btn-group.background + .d-flex( + *ngFor='let button of leftToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - window-controls.background( - *ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', - ) + .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') - start-page(*ngIf='ready && app.tabs.length == 0') + .btn-group.background + .d-flex( + *ngFor='let button of rightToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - tab-body( - *ngFor='let tab of unsortedTabs', - [active]='tab == app.activeTab', - [tab]='tab', - ) + button.btn.btn-secondary.btn-tab-bar.btn-update( + *ngIf='updatesAvailable', + title='Update available - Click to install', + (click)='updateApp()', + [fastHtmlBind]='updateIcon' + ) + + window-controls.background( + *ngIf='config.store.appearance.frame == "thin" \ + && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', + ) + + start-page(*ngIf='ready && app.tabs.length == 0') + + tab-body( + *ngFor='let tab of unsortedTabs', + [active]='tab == app.activeTab', + [tab]='tab', + ) ng-template(ngbModalContainer) diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index 689fc7f4..ddb38bf1 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -15,10 +15,18 @@ $tabs-height: 38px; $tab-border-radius: 4px; +$side-tab-width: 200px; +.wrap { + display: flex; + width: 100vw; + height: 100vh; + flex-direction: row; +} .content { - height: 100%; + width: 100vw; + height: 100vh; flex: auto; display: flex; flex-direction: column-reverse; @@ -26,12 +34,24 @@ $tab-border-radius: 4px; &.tabs-on-top { flex-direction: column; } + + &.with-side-tab { + width: calc(100% - #{$side-tab-width}); + } + } .tab-bar { flex: none; height: $tabs-height; display: flex; + width: 100%; + &.vertical { + height: 100%; + width: $side-tab-width; + overflow-y: auto; + overflow-x: hidden; + } .btn-tab-bar { line-height: $tabs-height + 2px; @@ -59,6 +79,12 @@ $tab-border-radius: 4px; flex: 0 1 auto; display: flex; min-width: 0; + + &.vertical { + width: $side-tab-width; + flex: auto; + flex-direction: column; + } } &>.drag-space { diff --git a/terminus-core/src/components/tabHeader.component.scss b/terminus-core/src/components/tabHeader.component.scss index 09ed4c87..1c5c45e5 100644 --- a/terminus-core/src/components/tabHeader.component.scss +++ b/terminus-core/src/components/tabHeader.component.scss @@ -13,6 +13,11 @@ $tabs-height: 38px; overflow: hidden; + &.vertical { + flex: none; + height: $tabs-height; + } + .index { flex: none; font-weight: bold; diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index 841e8744..b6369316 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -51,6 +51,13 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') [value]='"bottom"' ) | At the bottom + label.btn.btn-secondary(ngbButtonLabel) + input( + type='radio', + ngbButton, + [value]='"left"' + ) + | At the left .form-line .header diff --git a/terminus-settings/src/components/settingsTab.component.ts b/terminus-settings/src/components/settingsTab.component.ts index 4f26efd2..a10ad4ec 100644 --- a/terminus-settings/src/components/settingsTab.component.ts +++ b/terminus-settings/src/components/settingsTab.component.ts @@ -65,7 +65,7 @@ export class SettingsTabComponent extends BaseTabComponent { const onConfigChange = () => { this.configFile = config.readRaw() this.padWindowControls = hostApp.platform === Platform.macOS - && config.store.appearance.tabsLocation === 'bottom' + && config.store.appearance.tabsLocation !== 'top' } this.configSubscription = config.changed$.subscribe(onConfigChange) diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index 481b8097..bf0f2bcf 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -10,7 +10,7 @@ "scripts": { "build": "webpack --progress --color", "watch": "webpack --progress --color --watch", - "postinstall": "xcopy /i node_modules\\ssh2\\util\\pagent.exe util\\" + "postinstall": "xcopy /i /y node_modules\\ssh2\\util\\pagent.exe util\\" }, "files": [ "dist", diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index d949146a..16bd9dc5 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -348,7 +348,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit this.topPadded = this.hostApp.platform === Platform.macOS && this.config.store.appearance.frame === 'thin' - && this.config.store.appearance.tabsLocation === 'bottom' + && this.config.store.appearance.tabsLocation !== 'top' if (this.config.store.terminal.background === 'colorScheme') { if (this.config.store.terminal.colorScheme.background) { From dff6a2470c8bd081163a4ff0951c2c83d98ec600 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Sun, 6 Dec 2020 19:12:15 +0100 Subject: [PATCH 2/2] refined vertical tabs --- .../src/components/appRoot.component.pug | 212 ++++++++---------- .../src/components/appRoot.component.scss | 48 ++-- .../src/components/appRoot.component.ts | 4 + .../src/components/settingsTab.component.pug | 13 +- 4 files changed, 140 insertions(+), 137 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 887dfaf6..7630ade9 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -3,133 +3,105 @@ title-bar( [class.inset]='hostApp.platform == Platform.macOS' ) -.wrap - .tab-bar.vertical( - *ngIf='config.store.appearance.tabsLocation == "left"' - ) - .inset.background(*ngIf='hostApp.platform == Platform.macOS \ - && config.store.appearance.frame == "thin"') - .tabs.vertical( - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', +.content( + [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', + [class.tabs-on-side]='hasVerticalTabs()', +) + .tab-bar + .inset.background(*ngIf='hostApp.platform == Platform.macOS \ + && config.store.appearance.frame == "thin" \ + && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') + .tabs( + *ngIf='config.store.appearance.tabsLocation != "bottom"' + dnd-sortable-container, + [sortableData]='app.tabs', + ) + tab-header( + *ngFor='let tab of app.tabs; let idx = index', + dnd-sortable, + [sortableIndex]='idx', + (onDragStart)='onTabDragStart()', + (onDragEnd)='onTabDragEnd()', - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - [class.vertical]='true', - ) + [index]='idx', + [tab]='tab', + [active]='tab == app.activeTab', + [hasActivity]='tab.activity$|async', + @animateTab, + [@.disabled]='hasVerticalTabs()', + (click)='app.selectTab(tab)', + [class.fully-draggable]='hostApp.platform != Platform.macOS', + [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', + ) + .btn-group.background + .d-flex( + *ngFor='let button of leftToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .content( - [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"', - [class.with-side-tab]='config.store.appearance.tabsLocation == "left"', - ) - .tab-bar - .inset.background(*ngIf='hostApp.platform == Platform.macOS \ - && config.store.appearance.frame == "thin" \ - && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")') - .tabs( - *ngIf='config.store.appearance.tabsLocation != "left"' - dnd-sortable-container, - [sortableData]='app.tabs', - ) - tab-header( - *ngFor='let tab of app.tabs; let idx = index', - dnd-sortable, - [sortableIndex]='idx', - (onDragStart)='onTabDragStart()', - (onDragEnd)='onTabDragEnd()', + .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') - [index]='idx', - [tab]='tab', - [active]='tab == app.activeTab', - [hasActivity]='tab.activity$|async', - @animateTab, - (click)='app.selectTab(tab)', - [class.fully-draggable]='hostApp.platform != Platform.macOS', - [class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', - ) + .btn-group.background + .d-flex( + *ngFor='let button of rightToolbarButtons', + ngbDropdown, + (openChange)='generateButtonSubmenu(button)', + ) + button.btn.btn-secondary.btn-tab-bar( + [title]='button.title', + (click)='button.click && button.click()', + [fastHtmlBind]='button.icon', + ngbDropdownToggle, + ) + div(*ngIf='button.submenu', ngbDropdownMenu) + button.dropdown-item.d-flex.align-items-center( + *ngFor='let item of button.submenuItems', + (click)='item.click()', + ngbDropdownItem, + ) + .icon-wrapper( + *ngIf='hasIcons(button.submenuItems)', + [fastHtmlBind]='item.icon' + ) + div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} - .btn-group.background - .d-flex( - *ngFor='let button of leftToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + button.btn.btn-secondary.btn-tab-bar.btn-update( + *ngIf='updatesAvailable', + title='Update available - Click to install', + (click)='updateApp()', + [fastHtmlBind]='updateIcon' + ) - .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS') + window-controls.background( + *ngIf='config.store.appearance.frame == "thin" \ + && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', + ) - .btn-group.background - .d-flex( - *ngFor='let button of rightToolbarButtons', - ngbDropdown, - (openChange)='generateButtonSubmenu(button)', - ) - button.btn.btn-secondary.btn-tab-bar( - [title]='button.title', - (click)='button.click && button.click()', - [fastHtmlBind]='button.icon', - ngbDropdownToggle, - ) - div(*ngIf='button.submenu', ngbDropdownMenu) - button.dropdown-item.d-flex.align-items-center( - *ngFor='let item of button.submenuItems', - (click)='item.click()', - ngbDropdownItem, - ) - .icon-wrapper( - *ngIf='hasIcons(button.submenuItems)', - [fastHtmlBind]='item.icon' - ) - div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}} + start-page(*ngIf='ready && app.tabs.length == 0') - button.btn.btn-secondary.btn-tab-bar.btn-update( - *ngIf='updatesAvailable', - title='Update available - Click to install', - (click)='updateApp()', - [fastHtmlBind]='updateIcon' - ) - - window-controls.background( - *ngIf='config.store.appearance.frame == "thin" \ - && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', - ) - - start-page(*ngIf='ready && app.tabs.length == 0') - - tab-body( - *ngFor='let tab of unsortedTabs', - [active]='tab == app.activeTab', - [tab]='tab', - ) + tab-body( + *ngFor='let tab of unsortedTabs', + [active]='tab == app.activeTab', + [tab]='tab', + ) ng-template(ngbModalContainer) diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index ddb38bf1..76daa36b 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -35,26 +35,49 @@ $side-tab-width: 200px; flex-direction: column; } - &.with-side-tab { - width: calc(100% - #{$side-tab-width}); + &.tabs-on-side { + flex-direction: row-reverse; + + &.tabs-on-top { + flex-direction: row; + } } } +.content.tabs-on-side > .tab-bar { + height: 100%; + width: $side-tab-width; + overflow-y: auto; + overflow-x: hidden; + flex-direction: column; + background: rgba(0, 0, 0, 0.25); + + .tabs { + width: $side-tab-width; + flex: none; + flex-direction: column; + + tab-header { + flex: 0 0 $tabs-height; + } + } + + .drag-space { + flex: auto; + } +} + + .tab-bar { flex: none; height: $tabs-height; display: flex; width: 100%; - &.vertical { - height: 100%; - width: $side-tab-width; - overflow-y: auto; - overflow-x: hidden; - } .btn-tab-bar { line-height: $tabs-height + 2px; + height: $tabs-height; cursor: pointer; display: flex; @@ -79,12 +102,6 @@ $side-tab-width: 200px; flex: 0 1 auto; display: flex; min-width: 0; - - &.vertical { - width: $side-tab-width; - flex: auto; - flex-direction: column; - } } &>.drag-space { @@ -100,7 +117,10 @@ $side-tab-width: 200px; & > .inset { width: 85px; + height: $tabs-height; flex: none; + opacity: 0; + -webkit-app-region: drag; } window-controls { diff --git a/terminus-core/src/components/appRoot.component.ts b/terminus-core/src/components/appRoot.component.ts index 0ae1171f..16c06999 100644 --- a/terminus-core/src/components/appRoot.component.ts +++ b/terminus-core/src/components/appRoot.component.ts @@ -184,6 +184,10 @@ export class AppRootComponent { return false } + hasVerticalTabs () { + return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right' + } + async updateApp () { if ((await this.electron.showMessageBox( this.hostApp.getWindow(), diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index b6369316..7a787471 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -43,21 +43,28 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') ngbButton, [value]='"top"' ) - | On the top + | Top label.btn.btn-secondary(ngbButtonLabel) input( type='radio', ngbButton, [value]='"bottom"' ) - | At the bottom + | Bottom label.btn.btn-secondary(ngbButtonLabel) input( type='radio', ngbButton, [value]='"left"' ) - | At the left + | Left + label.btn.btn-secondary(ngbButtonLabel) + input( + type='radio', + ngbButton, + [value]='"right"' + ) + | Right .form-line .header