1
1
mirror of https://github.com/Eugeny/tabby.git synced 2024-12-25 11:33:35 +03:00

settings redesign

This commit is contained in:
Eugene Pankov 2018-08-25 09:37:56 +02:00
parent 64f670bd86
commit 06d14f9bb2
12 changed files with 522 additions and 338 deletions

View File

@ -2,6 +2,8 @@ import 'zone.js'
import 'core-js/es7/reflect' import 'core-js/es7/reflect'
import 'core-js/core/delay' import 'core-js/core/delay'
import 'rxjs' import 'rxjs'
import './global.scss'
import './toastr.scss' import './toastr.scss'
// Always land on the start view // Always land on the start view

87
app/src/global.scss Normal file
View File

@ -0,0 +1,87 @@
body {
min-height: 100vh;
overflow: hidden;
background: #1D272D;
}
.modal-dialog, .modal-backdrop {
-webkit-app-region: no-drag;
}
[ngbradiogroup] input[type="radio"] {
display: none;
}
.form-line {
display: flex;
border-top: 1px solid rgba(0, 0, 0, 0.2);
align-items: center;
padding: 10px 0;
margin: 0;
min-height: 64px;
.header {
margin-right: auto;
.title {
}
.description {
font-size: 13px;
opacity: .5;
}
}
&>.form-control, &>.input-group {
width: 33%;
}
}
input[type=range] {
-webkit-appearance: none;
background: transparent;
outline: none;
padding: 0;
&:focus {
border-color: transparent;
}
@mixin thumb() {
-webkit-appearance: none;
display: block;
height: 12px;
width: 12px;
background: #aaa;
border-radius: 6px;
cursor: pointer;
margin-top: -4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.95);
transition: 0.25s background;
&:hover {
background: #777;
}
&:active {
background: #666;
}
}
&::-webkit-slider-thumb { @include thumb(); }
&::-moz-range-thumb { @include thumb(); }
&::-ms-thumb { @include thumb(); }
&::thumb { @include thumb(); }
@mixin track() {
height: 4px;
background: #111;
margin: 3px 0 0;
box-sizing: border-box;
}
&::-webkit-slider-runnable-track { @include track(); }
&:focus::-webkit-slider-runnable-track { @include track(); }
&::-moz-range-track { @include track(); }
&::-ms-track { @include track(); }
}

View File

@ -58,17 +58,3 @@
color: #842fe0; color: #842fe0;
} }
} }
.modal-dialog, .modal-backdrop {
-webkit-app-region: no-drag;
}
[ngbradiogroup] input[type="radio"] {
display: none;
}
body {
min-height: 100vh;
overflow: hidden;
background: #1D272D;
}

View File

@ -1,4 +1,4 @@
.icon((click)='click()', tabindex='0', [class.active]='model', (keyup.space)='click()') .icon(tabindex='0', [class.active]='model', (keyup.space)='click()')
i.fa.fa-square-o.off i.fa.fa-square-o.off
i.fa.fa-check-square.on i.fa.fa-check-square.on
.text((click)='click()') {{text}} .text {{text}}

View File

@ -1,4 +1,4 @@
import { NgZone, Component, Input } from '@angular/core' import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
@Component({ @Component({
@ -10,12 +10,12 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
] ]
}) })
export class CheckboxComponent implements ControlValueAccessor { export class CheckboxComponent implements ControlValueAccessor {
@Input() model: boolean @HostBinding('class.active') @Input() model: boolean
@Input() disabled: boolean @Input() disabled: boolean
@Input() text: string @Input() text: string
private changed = new Array<(val: boolean) => void>() private changed = new Array<(val: boolean) => void>()
click () { @HostListener('click') click () {
NgZone.assertInAngularZone() NgZone.assertInAngularZone()
if (this.disabled) { if (this.disabled) {
return return

View File

@ -0,0 +1,70 @@
:host {
flex: none;
$toggle-size: 18px;
$height: 30px;
$padding: 2px;
cursor: pointer;
display: inline-flex;
overflow: visible;
border-radius: 3px;
line-height: $height;
height: $height;
transition: 0.25s opacity;
align-items: center;
overflow: hidden;
padding-right: 10px;
padding-left: 10px;
margin-left: -10px;
&:focus {
background: rgba(255,255,255,.05);
border-radius: 5px;
}
&[disabled] {
opacity: 0.5;
}
.body {
$border-width: 2px;
border-radius: 5px;
border: $border-width solid rgba(255, 255, 255, .2);
padding: $padding;
height: $toggle-size + $border-width * 2 + $padding * 2;
width: $toggle-size * 2 + $border-width * 2 + $padding * 2;
position: relative;
.toggle {
position: absolute;
border-radius: 2px;
width: $toggle-size;
height: $toggle-size;
background: #475158;
top: $padding;
left: $padding;
transition: 0.25s left;
line-height: 19px;
text-align: center;
font-size: 10px;
i {
opacity: 0;
transition: 0.25s opacity;
}
}
}
&.active .body .toggle {
left: $toggle-size + $padding;
i {
color: white;
opacity: 1;
}
}
&:active {
background: rgba(255,255,255,.1);
}
}

View File

@ -0,0 +1,22 @@
import { Component } from '@angular/core'
import { NG_VALUE_ACCESSOR } from '@angular/forms'
import { CheckboxComponent } from './checkbox.component'
@Component({
selector: 'toggle',
template: `
<div class="switch">
<div class="body">
<div class="toggle" [class.bg-primary]='model'>
<i class="fa fa-check"></i>
</div>
</div>
</div>
`,
styles: [require('./toggle.component.scss')],
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: ToggleComponent, multi: true },
]
})
export class ToggleComponent extends CheckboxComponent {
}

View File

@ -25,6 +25,7 @@ import { SafeModeModalComponent } from './components/safeModeModal.component'
import { StartPageComponent } from './components/startPage.component' import { StartPageComponent } from './components/startPage.component'
import { TabHeaderComponent } from './components/tabHeader.component' import { TabHeaderComponent } from './components/tabHeader.component'
import { TitleBarComponent } from './components/titleBar.component' import { TitleBarComponent } from './components/titleBar.component'
import { ToggleComponent } from './components/toggle.component'
import { WindowControlsComponent } from './components/windowControls.component' import { WindowControlsComponent } from './components/windowControls.component'
import { RenameTabModalComponent } from './components/renameTabModal.component' import { RenameTabModalComponent } from './components/renameTabModal.component'
@ -73,6 +74,7 @@ const PROVIDERS = [
TabBodyComponent, TabBodyComponent,
TabHeaderComponent, TabHeaderComponent,
TitleBarComponent, TitleBarComponent,
ToggleComponent,
WindowControlsComponent, WindowControlsComponent,
RenameTabModalComponent, RenameTabModalComponent,
SafeModeModalComponent, SafeModeModalComponent,
@ -82,7 +84,8 @@ const PROVIDERS = [
SafeModeModalComponent, SafeModeModalComponent,
], ],
exports: [ exports: [
CheckboxComponent CheckboxComponent,
ToggleComponent,
] ]
}) })
export default class AppModule { export default class AppModule {

View File

@ -352,3 +352,7 @@ select.form-control {
checkbox i.on { checkbox i.on {
color: $blue; color: $blue;
} }
toggle.active .body .toggle {
background: $blue;
}

View File

@ -6,21 +6,20 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
| Application | Application
ng-template(ngbTabContent) ng-template(ngbTabContent)
h3.mb-3 Application h3.mb-3 Application
.row .form-line
.col.col-lg-6 .header
.form-group .title Theme
label Theme
select.form-control( select.form-control(
'[(ngModel)]'='config.store.appearance.theme', [(ngModel)]='config.store.appearance.theme',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
option(*ngFor='let theme of themes', [ngValue]='theme.name') {{theme.name}} option(*ngFor='let theme of themes', [ngValue]='theme.name') {{theme.name}}
.form-group .form-line
label Show tabs .header
br .title Tabs location
.btn-group( .btn-group(
'[(ngModel)]'='config.store.appearance.tabsLocation', [(ngModel)]='config.store.appearance.tabsLocation',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
ngbRadioGroup ngbRadioGroup
) )
@ -39,12 +38,14 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
) )
| At the bottom | At the bottom
.form-group(*ngIf='hostApp.platform !== Platform.Linux') .form-line(*ngIf='hostApp.platform !== Platform.Linux')
label Vibrancy .header
br .title Vibrancy
.description Gives the window a blurred transparent background
.btn-group( .btn-group(
'[(ngModel)]'='config.store.appearance.vibrancy' [(ngModel)]='config.store.appearance.vibrancy',
'(ngModelChange)'='config.save(); (hostApp.platform === Platform.Windows && config.requestRestart())' (ngModelChange)='config.save(); (hostApp.platform === Platform.Windows && config.requestRestart())',
ngbRadioGroup ngbRadioGroup
) )
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
@ -62,25 +63,26 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
) )
| Disable | Disable
.form-group(*ngIf='hostApp.platform !== Platform.Linux') .form-line(*ngIf='hostApp.platform !== Platform.Linux')
label Opacity .header
br .title Window opacity
input( input(
type='range', type='range',
'[(ngModel)]'='config.store.appearance.opacity', [(ngModel)]='config.store.appearance.opacity',
'(ngModelChange)'='config.save()', (ngModelChange)='config.save()',
min='0.05', min='0.05',
max='1', max='1',
step='0.01' step='0.01'
) )
.col.col-lg-6 .form-line
.form-group .header
label Window frame .title Window frame
br .description Whether a custom window or an OS native window should be used
.btn-group( .btn-group(
'[(ngModel)]'='config.store.appearance.frame' [(ngModel)]='config.store.appearance.frame',
'(ngModelChange)'='config.save(); config.requestRestart()' (ngModelChange)='config.save(); config.requestRestart()',
ngbRadioGroup ngbRadioGroup
) )
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
@ -104,16 +106,15 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
[value]='"full"' [value]='"full"'
) )
| Full | Full
small.form-text.text-muted Whether a custom window or an OS native window should be used
.row .form-line
.col.col-auto .header
.form-group .title Dock the terminal
label Dock the terminal .description Snaps the window to a side of the screen
br
.btn-group( .btn-group(
'[(ngModel)]'='config.store.appearance.dock' [(ngModel)]='config.store.appearance.dock',
'(ngModelChange)'='config.save(); docking.dock()' (ngModelChange)='config.save(); docking.dock()',
ngbRadioGroup ngbRadioGroup
) )
label.btn.btn-secondary(ngbButtonLabel) label.btn.btn-secondary(ngbButtonLabel)
@ -152,9 +153,11 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
) )
| Bottom | Bottom
.form-group(*ngIf='config.store.appearance.dock != "off"') .form-line(*ngIf='config.store.appearance.dock != "off"')
label Display on .header
br .title Display on
.description Snaps the window to a side of the screen
div( div(
[(ngModel)]='config.store.appearance.dockScreen', [(ngModel)]='config.store.appearance.dockScreen',
(ngModelChange)='config.save(); docking.dock()', (ngModelChange)='config.save(); docking.dock()',
@ -174,31 +177,33 @@ ngb-tabset.vertical(type='tabs', [activeId]='activeTab')
[value]='screen.id' [value]='screen.id'
) )
| {{screen.name}} | {{screen.name}}
.col.col-auto
.form-group(*ngIf='config.store.appearance.dock != "off"') .form-line(*ngIf='config.store.appearance.dock != "off"')
label Docked terminal size .header
br .title Docked terminal size
input( input(
type='range', type='range',
'[(ngModel)]'='config.store.appearance.dockFill', [(ngModel)]='config.store.appearance.dockFill',
'(mouseup)'='config.save(); docking.dock()', (mouseup)='config.save(); docking.dock()',
min='0.05', min='0.05',
max='1', max='1',
step='0.01' step='0.01'
) )
.form-group .form-line
label Debugging .header
div .title Debugging
button.btn.btn-secondary((click)='hostApp.openDevTools()') button.btn.btn-secondary((click)='hostApp.openDevTools()')
i.fa.fa-bug i.fa.fa-bug
span Open DevTools span Open DevTools
.form-group .form-line
label Custom CSS .header
.title Custom CSS
textarea.form-control( textarea.form-control(
[(ngModel)]='config.store.appearance.css', [(ngModel)]='config.store.appearance.css',
'(ngModelChange)'='config.save()', (ngModelChange)='config.save()',
) )
ngb-tab(id='hotkeys') ngb-tab(id='hotkeys')

View File

@ -1,4 +1,4 @@
template(#content) ng-template(#content)
.preview( .preview(
[style.width]='"100%"', [style.width]='"100%"',
[style.background]='model', [style.background]='model',

View File

@ -1,33 +1,36 @@
h3.mb-3 Appearance h3.mb-3 Appearance
.row .row
.col-md-6 .col-md-6
.form-group .form-line
label Font .header
.row .title Font
.col-8
.d-flex.w-50
input.form-control( input.form-control(
type='text', type='text',
[ngbTypeahead]='fontAutocomplete', [ngbTypeahead]='fontAutocomplete',
[(ngModel)]='config.store.terminal.font', [(ngModel)]='config.store.terminal.font',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
.col-4
input.form-control( input.form-control(
type='number', type='number',
[(ngModel)]='config.store.terminal.fontSize', [(ngModel)]='config.store.terminal.fontSize',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
div .form-line
checkbox( .header
text='Enable font ligatures', .title Enable font ligatures
toggle(
[(ngModel)]='config.store.terminal.ligatures', [(ngModel)]='config.store.terminal.ligatures',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
.form-group(*ngIf='!editingColorScheme') .form-line(*ngIf='!editingColorScheme')
label Color scheme .header
.input-group .title Color scheme
.input-group.w-50
select.form-control( select.form-control(
[compareWith]='equalComparator', [compareWith]='equalComparator',
[(ngModel)]='config.store.terminal.colorScheme', [(ngModel)]='config.store.terminal.colorScheme',
@ -53,7 +56,6 @@ h3.mb-3 Appearance
.input-group-btn .input-group-btn
button.btn.btn-secondary((click)='cancelEditing()') Cancel button.btn.btn-secondary((click)='cancelEditing()') Cancel
.form-group(*ngIf='editingColorScheme') .form-group(*ngIf='editingColorScheme')
color-picker( color-picker(
'[(model)]'='editingColorScheme.foreground', '[(model)]'='editingColorScheme.foreground',
@ -77,9 +79,10 @@ h3.mb-3 Appearance
[title]='idx', [title]='idx',
) )
.form-group .form-line
label Terminal background .header
br .title Terminal background
.btn-group( .btn-group(
[(ngModel)]='config.store.terminal.background', [(ngModel)]='config.store.terminal.background',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
@ -100,59 +103,6 @@ h3.mb-3 Appearance
) )
| From colors | From colors
.d-flex
.form-group.mr-3
label Cursor shape
br
.btn-group(
[(ngModel)]='config.store.terminal.cursor',
(ngModelChange)='config.save()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"block"'
)
| █
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"beam"'
)
| |
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"underline"'
)
| ▁
.form-group
label Blink cursor
br
.btn-group(
[(ngModel)]='config.store.terminal.cursorBlink',
(ngModelChange)='config.save()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='false'
)
| Off
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='true'
)
| On
.col-md-6 .col-md-6
.form-group .form-group
.appearance-preview( .appearance-preview(
@ -240,11 +190,53 @@ h3.mb-3 Appearance
span rm -rf / span rm -rf /
span([style.background-color]='config.store.terminal.colorScheme.cursor') &nbsp; span([style.background-color]='config.store.terminal.colorScheme.cursor') &nbsp;
.form-line
.header
.title Cursor shape
.btn-group(
[(ngModel)]='config.store.terminal.cursor',
(ngModelChange)='config.save()',
ngbRadioGroup
)
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"block"'
)
| █
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"beam"'
)
| |
label.btn.btn-secondary(ngbButtonLabel)
input(
type='radio',
ngbButton,
[value]='"underline"'
)
| ▁
.form-line
.header
.title Blink cursor
toggle(
[(ngModel)]='config.store.terminal.cursorBlink',
(ngModelChange)='config.save()',
)
h3.mt-3.mb-3 Shell h3.mt-3.mb-3 Shell
.d-flex .form-line
.form-group.mr-3 .header
label Shell .title Shell
.description Default shell for new tabs
select.form-control( select.form-control(
[(ngModel)]='config.store.terminal.shell', [(ngModel)]='config.store.terminal.shell',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
@ -254,8 +246,20 @@ h3.mt-3.mb-3 Shell
[ngValue]='shell.id' [ngValue]='shell.id'
) {{shell.name}} ) {{shell.name}}
.form-group.mr-3(*ngIf='persistenceProviders.length > 0') .form-line(*ngIf='config.store.terminal.shell == "custom"')
label Session persistence .header
.title Custom shell
input.form-control(
type='text',
[(ngModel)]='config.store.terminal.customShell',
(ngModelChange)='config.save()',
)
.form-line(*ngIf='persistenceProviders.length > 0')
.header
.title Session persistence
.description Restores tabs when Terminus is restarted
select.form-control( select.form-control(
[(ngModel)]='config.store.terminal.persistence', [(ngModel)]='config.store.terminal.persistence',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
@ -266,8 +270,9 @@ h3.mt-3.mb-3 Shell
[ngValue]='provider.id' [ngValue]='provider.id'
) {{provider.displayName}} ) {{provider.displayName}}
.form-group .form-line
label Working directory .header
.title Working directory
input.form-control( input.form-control(
type='text', type='text',
placeholder='Home directory', placeholder='Home directory',
@ -275,20 +280,11 @@ h3.mt-3.mb-3 Shell
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
.form-group(*ngIf='config.store.terminal.shell == "custom"')
label Custom shell
input.form-control(
type='text',
[(ngModel)]='config.store.terminal.customShell',
(ngModelChange)='config.save()',
)
h3.mt-3.mb-3 Behaviour h3.mt-3.mb-3 Behaviour
.form-group .form-line
label Terminal bell .header
br .title Terminal bell
.btn-group( .btn-group(
[(ngModel)]='config.store.terminal.bell', [(ngModel)]='config.store.terminal.bell',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
@ -316,9 +312,9 @@ h3.mt-3.mb-3 Behaviour
) )
| Audible | Audible
.form-group .form-line
label Right click .header
br .title Right click
.btn-group( .btn-group(
[(ngModel)]='config.store.terminal.rightClick', [(ngModel)]='config.store.terminal.rightClick',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
@ -339,28 +335,37 @@ h3.mt-3.mb-3 Behaviour
) )
| Paste | Paste
.form-line
.header
.title Auto-open a terminal on app start
.form-group toggle(
checkbox(
[(ngModel)]='config.store.terminal.autoOpen', [(ngModel)]='config.store.terminal.autoOpen',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
text='Auto-open a terminal on app start',
) )
checkbox( .form-line
.header
.title Bracketed paste (requires shell support)
.description Prevents accidental execution of pasted commands
toggle(
[(ngModel)]='config.store.terminal.bracketedPaste', [(ngModel)]='config.store.terminal.bracketedPaste',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
text='Bracketed paste (requires shell support)',
) )
checkbox( .form-line
.header
.title Copy on select
toggle(
[(ngModel)]='config.store.terminal.copyOnSelect', [(ngModel)]='config.store.terminal.copyOnSelect',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
text='Copy on select',
) )
checkbox( .form-line
.header
.title Use Alt key as the Meta key
.description Lets the shell handle Meta key instead of OS
toggle(
[(ngModel)]='config.store.terminal.altIsMeta', [(ngModel)]='config.store.terminal.altIsMeta',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
text='Use Alt key as the Meta key',
) )