refined vertical tabs

This commit is contained in:
Eugene Pankov 2020-12-06 19:12:15 +01:00
parent cbebc09504
commit dff6a2470c
No known key found for this signature in database
GPG Key ID: 5896FCBBDD1CF4F4
4 changed files with 140 additions and 137 deletions

View File

@ -3,133 +3,105 @@ title-bar(
[class.inset]='hostApp.platform == Platform.macOS' [class.inset]='hostApp.platform == Platform.macOS'
) )
.wrap .content(
.tab-bar.vertical( [class.tabs-on-top]='config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left"',
*ngIf='config.store.appearance.tabsLocation == "left"' [class.tabs-on-side]='hasVerticalTabs()',
) )
.inset.background(*ngIf='hostApp.platform == Platform.macOS \ .tab-bar
&& config.store.appearance.frame == "thin"') .inset.background(*ngIf='hostApp.platform == Platform.macOS \
.tabs.vertical( && config.store.appearance.frame == "thin" \
dnd-sortable-container, && (config.store.appearance.tabsLocation == "top" || config.store.appearance.tabsLocation == "left")')
[sortableData]='app.tabs', .tabs(
) *ngIf='config.store.appearance.tabsLocation != "bottom"'
tab-header( dnd-sortable-container,
*ngFor='let tab of app.tabs; let idx = index', [sortableData]='app.tabs',
dnd-sortable, )
[sortableIndex]='idx', tab-header(
(onDragStart)='onTabDragStart()', *ngFor='let tab of app.tabs; let idx = index',
(onDragEnd)='onTabDragEnd()', dnd-sortable,
[sortableIndex]='idx',
(onDragStart)='onTabDragStart()',
(onDragEnd)='onTabDragEnd()',
[index]='idx', [index]='idx',
[tab]='tab', [tab]='tab',
[active]='tab == app.activeTab', [active]='tab == app.activeTab',
[hasActivity]='tab.activity$|async', [hasActivity]='tab.activity$|async',
@animateTab, @animateTab,
(click)='app.selectTab(tab)', [@.disabled]='hasVerticalTabs()',
[class.fully-draggable]='hostApp.platform != Platform.macOS', (click)='app.selectTab(tab)',
[class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', [class.fully-draggable]='hostApp.platform != Platform.macOS',
[class.vertical]='true', [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( .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
[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()',
[index]='idx', .btn-group.background
[tab]='tab', .d-flex(
[active]='tab == app.activeTab', *ngFor='let button of rightToolbarButtons',
[hasActivity]='tab.activity$|async', ngbDropdown,
@animateTab, (openChange)='generateButtonSubmenu(button)',
(click)='app.selectTab(tab)', )
[class.fully-draggable]='hostApp.platform != Platform.macOS', button.btn.btn-secondary.btn-tab-bar(
[class.drag-region]='hostApp.platform == Platform.macOS && !tabsDragging', [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 button.btn.btn-secondary.btn-tab-bar.btn-update(
.d-flex( *ngIf='updatesAvailable',
*ngFor='let button of leftToolbarButtons', title='Update available - Click to install',
ngbDropdown, (click)='updateApp()',
(openChange)='generateButtonSubmenu(button)', [fastHtmlBind]='updateIcon'
) )
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') window-controls.background(
*ngIf='config.store.appearance.frame == "thin" \
&& (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)',
)
.btn-group.background start-page(*ngIf='ready && app.tabs.length == 0')
.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}}
button.btn.btn-secondary.btn-tab-bar.btn-update( tab-body(
*ngIf='updatesAvailable', *ngFor='let tab of unsortedTabs',
title='Update available - Click to install', [active]='tab == app.activeTab',
(click)='updateApp()', [tab]='tab',
[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) ng-template(ngbModalContainer)

View File

@ -35,26 +35,49 @@ $side-tab-width: 200px;
flex-direction: column; flex-direction: column;
} }
&.with-side-tab { &.tabs-on-side {
width: calc(100% - #{$side-tab-width}); 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 { .tab-bar {
flex: none; flex: none;
height: $tabs-height; height: $tabs-height;
display: flex; display: flex;
width: 100%; width: 100%;
&.vertical {
height: 100%;
width: $side-tab-width;
overflow-y: auto;
overflow-x: hidden;
}
.btn-tab-bar { .btn-tab-bar {
line-height: $tabs-height + 2px; line-height: $tabs-height + 2px;
height: $tabs-height;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@ -79,12 +102,6 @@ $side-tab-width: 200px;
flex: 0 1 auto; flex: 0 1 auto;
display: flex; display: flex;
min-width: 0; min-width: 0;
&.vertical {
width: $side-tab-width;
flex: auto;
flex-direction: column;
}
} }
&>.drag-space { &>.drag-space {
@ -100,7 +117,10 @@ $side-tab-width: 200px;
& > .inset { & > .inset {
width: 85px; width: 85px;
height: $tabs-height;
flex: none; flex: none;
opacity: 0;
-webkit-app-region: drag;
} }
window-controls { window-controls {

View File

@ -184,6 +184,10 @@ export class AppRootComponent {
return false return false
} }
hasVerticalTabs () {
return this.config.store.appearance.tabsLocation === 'left' || this.config.store.appearance.tabsLocation === 'right'
}
async updateApp () { async updateApp () {
if ((await this.electron.showMessageBox( if ((await this.electron.showMessageBox(
this.hostApp.getWindow(), this.hostApp.getWindow(),

View File

@ -43,21 +43,28 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngbButton, ngbButton,
[value]='"top"' [value]='"top"'
) )
| On the top | Top
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
input( input(
type='radio', type='radio',
ngbButton, ngbButton,
[value]='"bottom"' [value]='"bottom"'
) )
| At the bottom | Bottom
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
input( input(
type='radio', type='radio',
ngbButton, ngbButton,
[value]='"left"' [value]='"left"'
) )
| At the left | Left
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"right"'
)
| Right
.form-line .form-line
.header .header