mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-25 13:59:52 +00:00
refined vertical tabs
This commit is contained in:
parent
cbebc09504
commit
dff6a2470c
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
@ -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(),
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user