1
0
mirror of https://github.com/Eugeny/tabby.git synced 2025-07-11 22:09:52 +00:00

ui tweaks

This commit is contained in:
Eugene Pankov 2019-12-15 16:57:38 +01:00
parent 786daaac32
commit b6c97ffa49
16 changed files with 417 additions and 336 deletions

@ -47,8 +47,11 @@ title-bar(
(click)='item.click()', (click)='item.click()',
ngbDropdownItem, ngbDropdownItem,
) )
.icon-wrapper([innerHTML]='sanitizeIcon(item.icon)') .icon-wrapper(
.ml-3 {{item.title}} *ngIf='hasIcons(button.submenuItems)',
[innerHTML]='sanitizeIcon(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') .drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
@ -70,8 +73,11 @@ title-bar(
(click)='item.click()', (click)='item.click()',
ngbDropdownItem, ngbDropdownItem,
) )
.icon-wrapper([innerHTML]='sanitizeIcon(item.icon)') .icon-wrapper(
.ml-3 {{item.title}} *ngIf='hasIcons(button.submenuItems)',
[innerHTML]='sanitizeIcon(item.icon)'
)
div([class.ml-3]='hasIcons(button.submenuItems)') {{item.title}}
button.btn.btn-secondary.btn-tab-bar.btn-update( button.btn.btn-secondary.btn-tab-bar.btn-update(
*ngIf='updatesAvailable', *ngIf='updatesAvailable',

@ -250,6 +250,10 @@ export class AppRootComponent {
} }
} }
hasIcons (submenuItems: ToolbarButton[]): boolean {
return submenuItems.some(x => !!x.icon)
}
sanitizeIcon (icon: string): any { sanitizeIcon (icon: string): any {
return this.domSanitizer.bypassSecurityTrustHtml(icon || '') return this.domSanitizer.bypassSecurityTrustHtml(icon || '')
} }

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

@ -1,55 +0,0 @@
:host {
cursor: pointer;
margin: 5px 0;
&:focus {
background: rgba(255,255,255,.05);
border-radius: 5px;
}
&:active {
background: rgba(255,255,255,.1);
border-radius: 3px;
}
&[disabled] {
opacity: 0.5;
}
display: flex;
flex-direction: row;
align-items: center;
.off {
color: rgba(0, 0, 0, .5);
}
.icon {
position: relative;
flex: none;
width: 14px;
height: 14px;
i {
position: absolute;
left: 0;
top: -2px;
transition: 0.25s opacity;
display: block;
font-size: 18px;
}
i.on, &.active i.off {
opacity: 0;
}
i.off, &.active i.on {
opacity: 1;
}
}
.text {
flex: auto;
margin-left: 8px;
}
}

@ -4,8 +4,12 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
/** @hidden */ /** @hidden */
@Component({ @Component({
selector: 'checkbox', selector: 'checkbox',
template: require('./checkbox.component.pug'), template: `
styles: [require('./checkbox.component.scss')], <div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" [(ngModel)]='model'>
<label class="custom-control-label">{{text}}</label>
</div>
`,
providers: [ providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: CheckboxComponent, multi: true }, { provide: NG_VALUE_ACCESSOR, useExisting: CheckboxComponent, multi: true },
], ],

@ -48,7 +48,7 @@ $tabs-height: 38px;
width: $button-size; width: $button-size;
height: $button-size; height: $button-size;
border-radius: $button-size / 2; border-radius: $button-size / 2;
line-height: $button-size * 0.9; line-height: $button-size;
align-self: center; align-self: center;
margin-right: 10px; margin-right: 10px;

@ -16,55 +16,8 @@
padding-left: 10px; padding-left: 10px;
margin-left: -10px; margin-left: -10px;
&:focus {
background: rgba(255,255,255,.05);
border-radius: 5px;
}
&[disabled] { &[disabled] {
opacity: 0.5; 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);
}
} }

@ -6,13 +6,10 @@ import { CheckboxComponent } from './checkbox.component'
@Component({ @Component({
selector: 'toggle', selector: 'toggle',
template: ` template: `
<div class="switch"> <div class="custom-control custom-switch">
<div class="body"> <input type="checkbox" class="custom-control-input" [(ngModel)]='model'>
<div class="toggle" [class.bg-primary]='model'> <label class="custom-control-label"></label>
<i class="fa fa-check"></i> </div>
</div>
</div>
</div>
`, `,
styles: [require('./toggle.component.scss')], styles: [require('./toggle.component.scss')],
providers: [ providers: [

@ -1,103 +1,11 @@
$tab-border-radius: 5px; @import "./theme.vars";
// ---------
$button-hover-bg: rgba(0, 0, 0, .25); $button-hover-bg: rgba(0, 0, 0, .25);
$button-active-bg: rgba(0, 0, 0, .5); $button-active-bg: rgba(0, 0, 0, .5);
$white: #fff !default;
$black: #000 !default;
$red: #d9534f !default;
$orange: #f0ad4e !default;
$yellow: #ffd500 !default;
$green: #5cb85c !default;
$blue: #0275d8 !default;
$teal: #5bc0de !default;
$pink: #ff5b77 !default;
$purple: #613d7c !default;
$theme-colors: (
"primary": $blue,
"secondary": #394b5d
);
$content-bg: rgba(39, 49, 60, 0.65); //#1D272D;
$content-bg-solid: #1D272D;
$body-bg: #131d27;
$body-bg2: #20333e;
$body-color: #ccc;
$font-family-sans-serif: "Source Sans Pro";
$font-family-monospace: "Source Code Pro";
$font-size-base: 14rem / 16;
$btn-border-radius: 0;
$btn-secondary-color: #ccc;
$btn-secondary-bg: #222;
$btn-secondary-border: #444;
//$btn-warning-bg: rgba($orange, .5);
$nav-tabs-border-width: 0;
$nav-tabs-border-radius: 0;
$nav-tabs-link-hover-border-color: $body-bg;
$nav-tabs-active-link-hover-color: $white;
$nav-tabs-active-link-hover-bg: $blue;
$nav-tabs-active-link-hover-border-color: darken($blue, 30%);
$nav-pills-border-radius: 0;
$input-bg: #111;
$input-disabled-bg: #333;
$input-color: $body-color;
$input-color-placeholder: #333;
$input-border-color: #344;
$input-border-width: 1px;
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
$input-border-radius: 0;
$custom-select-border-radius: 0;
$input-bg-focus: $input-bg;
$input-border-focus: lighten($blue, 25%);
$input-focus-box-shadow: none;
$input-color-focus: $input-color;
$input-group-addon-bg: $body-bg;
$input-group-addon-border-color: $input-border-color;
$modal-content-bg: $content-bg-solid;
$modal-content-border-color: $body-bg;
$modal-header-border-color: transparent;
$modal-footer-border-color: transparent;
$popover-bg: $body-bg;
$dropdown-bg: $body-bg;
$dropdown-link-color: $body-color;
$dropdown-link-hover-color: white;
$dropdown-link-hover-bg: $body-bg2;
//$dropdown-link-active-color: $component-active-color;
//$dropdown-link-active-bg: $component-active-bg;
$dropdown-link-disabled-color: #333;
$dropdown-header-color: #333;
$list-group-color: $body-color;
$list-group-bg: rgba(255,255,255,.05);
$list-group-border-color: rgba(255,255,255,.1);
$list-group-hover-bg: rgba(255,255,255,.1);
$list-group-link-active-bg: rgba(255,255,255,.2);
$list-group-action-color: $body-color;
$list-group-action-bg: rgba(255,255,255,.05);
$list-group-action-active-bg: $list-group-link-active-bg;
$pre-bg: $dropdown-bg;
$pre-color: $dropdown-link-color;
$alert-danger-bg: $body-bg;
$alert-danger-text: $red;
$alert-danger-border: $red;
$headings-font-weight: lighter;
$headings-color: #eee;
@import '~bootstrap/scss/bootstrap.scss'; @import '~bootstrap/scss/bootstrap.scss';
window-controls { window-controls {
@ -236,13 +144,14 @@ settings-tab > ngb-tabset {
border: none; border: none;
padding: 10px 50px 10px 20px; padding: 10px 50px 10px 20px;
font-size: 14px; font-size: 14px;
border-radius: 0;
&:not(.active) { &:not(.active) {
color: $body-color; color: $body-color;
&:hover { &:hover {
color: $white; color: $white;
} }
} }
} }
} }
@ -310,14 +219,6 @@ hotkey-input-modal {
margin-bottom: 2px; margin-bottom: 2px;
} }
.nav-tabs {
background: $btn-secondary-bg;
.nav-link {
transition: 0.25s all;
border-bottom-color: $nav-tabs-border-color;
}
}
ngb-tabset .tab-content { ngb-tabset .tab-content {
padding-top: 20px; padding-top: 20px;
} }
@ -361,22 +262,10 @@ ngb-tabset .tab-content {
} }
} }
select.form-control {
-webkit-appearance: none;
background-image: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='24' height='24' viewBox='0 0 24 24'><path fill='#444' d='M7.406 7.828l4.594 4.594 4.594-4.594 1.406 1.406-6 6-6-6z'></path></svg>");
background-position: 100% 50%;
background-repeat: no-repeat;
padding-right: 30px;
}
checkbox i.on { checkbox i.on {
color: $blue; color: $blue;
} }
toggle.active .body .toggle {
background: $blue;
}
.modal .modal-footer { .modal .modal-footer {
background: rgba(0, 0, 0, .25); background: rgba(0, 0, 0, .25);
@ -409,3 +298,97 @@ toggle.active .body .toggle {
search-panel { search-panel {
background: rgba(39, 49, 60, 0.65) !important; background: rgba(39, 49, 60, 0.65) !important;
} }
.btn {
cursor: pointer;
justify-content: flex-start;
overflow: hidden;
&.disabled,
&:disabled {
cursor: not-allowed;
}
}
.btn.btn-outline-secondary {
@include button-outline-variant(#9badb9, #fff);
&:hover:not([disabled]), &:active:not([disabled]), &.active:not([disabled]) {
background-color: #3f484e;
border-color: darken(#9badb9, 25%);
}
border-color: darken(#9badb9, 25%);
&.disabled,
&:disabled {
color: #9badb9;
}
}
.btn-warning:not(:disabled):not(.disabled) {
&.active, &:active {
color: $gray-900;
}
}
.btn-secondary:not(:disabled):not(.disabled) {
&.active, &:active {
background: #191e23;
}
}
.btn-link {
&:hover, &[aria-expanded=true], &:active, &.active {
color: $link-hover-color;
border-radius: $btn-border-radius;
}
&[aria-expanded=true], &:active, &.active {
background: rgba(255, 255, 255, 0.1);
}
}
.btn-group .btn.active {
border-color: transparent !important;
}
.nav-tabs {
margin-bottom: 10px;
&.nav-justified .nav-link {
margin-right: 5px;
}
.nav-link {
border: none;
border-bottom: $nav-tabs-border-width solid transparent;
text-transform: uppercase;
font-weight: bold;
padding: 5px 0;
margin-right: 20px;
uib-tab-heading > i {
font-size: 18px;
}
@include hover-focus {
color: $nav-tabs-link-active-color;
}
&.disabled {
color: $nav-link-disabled-color;
border-color: transparent;
}
}
.nav-item:last-child .nav-link {
margin-right: 0;
}
.nav-link.active,
.nav-item.show .nav-link {
color: $nav-tabs-link-active-color;
border-color: $nav-tabs-link-active-border-color;
}
}

@ -0,0 +1,187 @@
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000;
$red: #d9534f !default;
$orange: #f0ad4e !default;
$yellow: #ffd500 !default;
$green: #5cb85c !default;
$blue: #0275d8 !default;
$teal: #5bc0de !default;
$pink: #ff5b77 !default;
$purple: #613d7c !default;
@import "~bootstrap/scss/functions";
$content-bg: rgba(39, 49, 60, 0.65); //#1D272D;
$content-bg-solid: #1D272D;
$table-bg: rgba(255,255,255,.05);
$table-bg-hover: rgba(255,255,255,.1);
$table-border-color: rgba(255,255,255,.1);
$theme-colors: (
primary: $blue,
secondary: #38434e,
success: $green,
info: $blue,
warning: $orange,
danger: $red,
light: $gray-300,
dark: $gray-800,
rare: $purple
);
$body-color: #ccc;
$body-bg: #131d27;
$body-bg2: #20333e;
$font-family-sans-serif: "Source Sans Pro";
$font-family-monospace: "Source Code Pro";
$font-size-base: 14rem / 16;
$font-size-lg: 1.28rem;
$font-size-sm: .85rem;
$line-height-base: 1.6;
$headings-color: #ced9e2;
$headings-font-weight: lighter;
$input-btn-padding-y: .3rem;
$input-btn-padding-x: .9rem;
$input-btn-line-height: 1.6;
$input-btn-line-height-sm: 1.8;
$input-btn-line-height-lg: 1.8;
$btn-link-disabled-color: $gray-600;
$btn-focus-box-shadow: none;
$h4-font-size: 18px;
$link-color: $gray-400;
$link-hover-color: $white;
$link-hover-decoration: none;
$component-active-color: $white;
$component-active-bg: #2f3a42;
$list-group-bg: $table-bg;
$list-group-border-color: $table-border-color;
$list-group-item-padding-y: 0.8rem;
$list-group-item-padding-x: 1rem;
$list-group-hover-bg: $table-bg-hover;
$list-group-active-bg: rgba(255,255,255,.2);
$list-group-active-color: $component-active-color;
$list-group-active-border-color: translate;
$list-group-action-color: $body-color;
$list-group-action-hover-color: white;
$list-group-action-active-color: $component-active-color;
$list-group-action-active-bg: $list-group-active-bg;
$alert-padding-y: 0.9rem;
$alert-padding-x: 1.25rem;
$input-box-shadow: none;
$transition-base: all .15s ease-in-out;
$transition-fade: opacity .1s linear;
$transition-collapse: height .35s ease;
$btn-transition: all .15s ease-in-out;
$popover-bg: $body-bg;
$popover-body-color: $body-color;
$popover-header-bg: $table-bg-hover;
$popover-header-color: $headings-color;
$popover-arrow-color: $popover-bg;
$popover-max-width: 360px;
$btn-border-width: 2px;
$input-bg: #181e23;
$input-disabled-bg: #2e3235;
$input-color: #ddd;
$input-border-color: $input-bg;
$input-border-width: 2px;
$input-focus-bg: $input-bg;
$input-focus-border-color: rgba(171, 171, 171, 0.61);
$input-focus-color: $input-color;
$input-btn-focus-color: var(--focus-color);
$input-btn-focus-box-shadow: 0 0 0 2px $input-btn-focus-color;
$input-group-addon-color: $input-color;
$input-group-addon-bg: $input-bg;
$input-group-addon-border-color: transparent;
$input-group-btn-border-color: $input-bg;
$nav-tabs-border-radius: 0;
$nav-tabs-border-color: transparent;
$nav-tabs-border-width: 2px;
$nav-tabs-link-hover-border-color: transparent;
$nav-tabs-link-active-color: #eee;
$nav-tabs-link-active-bg: transparent;
$nav-tabs-link-active-border-color: #eee;
$navbar-padding-y: 0;
$navbar-padding-x: 0;
$dropdown-bg: $table-bg;
$dropdown-color: $body-color;
$dropdown-border-width: 1px;
$dropdown-box-shadow: 0 .5rem 1rem rgba($black,.175);
$dropdown-header-color: $gray-500;
$dropdown-link-color: $body-color;
$dropdown-link-hover-color: #eee;
$dropdown-link-hover-bg: rgba(255,255,255,.04);
$dropdown-link-active-color: white;
$dropdown-link-active-bg: rgba(0, 0, 0, .2);
$dropdown-item-padding-y: 0.5rem;
$dropdown-item-padding-x: 1.5rem;
$code-color: $orange;
$code-bg: rgba(0, 0, 0, .25);
$code-padding-y: 3px;
$code-padding-x: 5px;
$pre-bg: $dropdown-bg;
$pre-color: $dropdown-link-color;
$badge-font-size: 0.75rem;
$badge-font-weight: bold;
$badge-padding-y: 4px;
$badge-padding-x: 6px;
$custom-control-indicator-size: 1.2rem;
$custom-control-indicator-bg: $body-bg;
$custom-control-indicator-border-color: lighten($body-bg, 25%);
$custom-control-indicator-checked-bg: theme-color("primary");
$custom-control-indicator-checked-color: $body-bg;
$custom-control-indicator-checked-border-color: transparent;
$custom-control-indicator-active-bg: rgba(255, 255, 0, 0.5);
$modal-content-bg: $content-bg-solid;
$modal-content-border-color: $body-bg;
$modal-header-border-width: 0;
$modal-footer-border-color: #222;
$modal-footer-border-width: 1px;
$modal-content-border-width: 0;

@ -5,7 +5,7 @@
.d-flex .d-flex
h3.mb-1 Installed h3.mb-1 Installed
button.btn.btn-outline-info.btn-sm.ml-auto((click)='openPluginsFolder()') button.btn.btn-outline-secondary.btn-sm.ml-auto((click)='openPluginsFolder()')
i.fas.fa-folder i.fas.fa-folder
span Plugins folder span Plugins folder
@ -28,19 +28,19 @@
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing') i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
span Upgrade ({{knownUpgrades[plugin.name].version}}) span Upgrade ({{knownUpgrades[plugin.name].version}})
button.btn.btn-primary.ml-2( button.btn.btn-link.text-primary.ml-2(
*ngIf='config.store.pluginBlacklist.includes(plugin.name)', *ngIf='config.store.pluginBlacklist.includes(plugin.name)',
(click)='enablePlugin(plugin)' (click)='enablePlugin(plugin)'
) )
i.fas.fa-fw.fa-play i.fas.fa-fw.fa-play
button.btn.btn-secondary.ml-2( button.btn.btn-link.ml-2(
*ngIf='!config.store.pluginBlacklist.includes(plugin.name)', *ngIf='!config.store.pluginBlacklist.includes(plugin.name)',
(click)='disablePlugin(plugin)' (click)='disablePlugin(plugin)'
) )
i.fas.fa-fw.fa-pause i.fas.fa-fw.fa-pause
button.btn.btn-danger.ml-2( button.btn.btn-link.text-danger.ml-2(
(click)='uninstallPlugin(plugin)', (click)='uninstallPlugin(plugin)',
*ngIf='!plugin.isBuiltin', *ngIf='!plugin.isBuiltin',
[disabled]='busy[plugin.name] != undefined' [disabled]='busy[plugin.name] != undefined'

@ -1,69 +1,69 @@
.modal-body .modal-body
ngb-tabset(type='pills', [activeId]='basic') ngb-tabset([activeId]='basic')
ngb-tab(id='basic') ngb-tab(id='basic')
ng-template(ngbTabTitle) General ng-template(ngbTabTitle) General
ng-template(ngbTabContent) ng-template(ngbTabContent)
.form-group .form-group
label Name label Name
input.form-control( input.form-control(
type='text', type='text',
autofocus, autofocus,
[(ngModel)]='connection.name', [(ngModel)]='connection.name',
) )
.form-group .form-group
label Group label Group
input.form-control( input.form-control(
type='text', type='text',
placeholder='Ungrouped', placeholder='Ungrouped',
[(ngModel)]='connection.group', [(ngModel)]='connection.group',
) )
.form-group .form-group
label Host label Host
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='connection.host', [(ngModel)]='connection.host',
) )
.form-group .form-group
label Port label Port
input.form-control( input.form-control(
type='number', type='number',
placeholder='22', placeholder='22',
[(ngModel)]='connection.port', [(ngModel)]='connection.port',
) )
.form-group .form-group
label Username label Username
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='connection.user', [(ngModel)]='connection.user',
) )
.form-line .form-line
.header .header
.title Password .title Password
.description(*ngIf='!hasSavedPassword') Save a password in the keychain .description(*ngIf='!hasSavedPassword') Save a password in the keychain
.description(*ngIf='hasSavedPassword') There is a saved password for this connection .description(*ngIf='hasSavedPassword') There is a saved password for this connection
button.btn.btn-outline-success.ml-4(*ngIf='!hasSavedPassword', (click)='setPassword()') button.btn.btn-outline-success.ml-4(*ngIf='!hasSavedPassword', (click)='setPassword()')
i.fas.fa-key i.fas.fa-key
span Set password span Set password
button.btn.btn-danger.ml-4(*ngIf='hasSavedPassword', (click)='clearSavedPassword()') button.btn.btn-danger.ml-4(*ngIf='hasSavedPassword', (click)='clearSavedPassword()')
i.fas.fa-trash-alt i.fas.fa-trash-alt
span Forget span Forget
.form-line .form-line
.header .header
.title Private key .title Private key
.description Path to the private key file .description Path to the private key file
.input-group .input-group
input.form-control( input.form-control(
type='text', type='text',
placeholder='Key file path', placeholder='Key file path',
[(ngModel)]='connection.privateKey' [(ngModel)]='connection.privateKey'
) )
.input-group-btn .input-group-append
button.btn.btn-secondary((click)='selectPrivateKey()') button.btn.btn-secondary((click)='selectPrivateKey()')
i.fas.fa-folder-open i.fas.fa-folder-open
@ -73,27 +73,27 @@
.form-group .form-group
label Keep Alive Interval (Milliseconds) label Keep Alive Interval (Milliseconds)
input.form-control( input.form-control(
type='number', type='number',
placeholder='0', placeholder='0',
[(ngModel)]='connection.keepaliveInterval', [(ngModel)]='connection.keepaliveInterval',
) )
.form-group .form-group
label Max Keep Alive Count label Max Keep Alive Count
input.form-control( input.form-control(
type='number', type='number',
placeholder='3', placeholder='3',
[(ngModel)]='connection.keepaliveCountMax', [(ngModel)]='connection.keepaliveCountMax',
) )
.form-group .form-group
label Ready Timeout (Milliseconds) label Ready Timeout (Milliseconds)
input.form-control( input.form-control(
type='number', type='number',
placeholder='20000', placeholder='20000',
[(ngModel)]='connection.readyTimeout', [(ngModel)]='connection.readyTimeout',
) )
.form-group .form-group
label Ciphers label Ciphers
div(*ngFor='let alg of supportedAlgorithms.cipher') div(*ngFor='let alg of supportedAlgorithms.cipher')
@ -128,12 +128,12 @@
tr(*ngFor='let script of connection.scripts') tr(*ngFor='let script of connection.scripts')
td.pr-2 td.pr-2
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='script.expect' [(ngModel)]='script.expect'
) )
td td
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='script.send' [(ngModel)]='script.send'
) )
td.pl-2 td.pl-2
@ -152,11 +152,11 @@
i.fas.fa-arrow-down i.fas.fa-arrow-down
button.btn.btn-outline-danger.ml-0((click)='deleteScript(script)') button.btn.btn-outline-danger.ml-0((click)='deleteScript(script)')
i.fas.fa-trash i.fas.fa-trash
button.btn.btn-outline-info.mt-2((click)='addScript()') button.btn.btn-outline-info.mt-2((click)='addScript()')
i.fas.fa-plus i.fas.fa-plus
span New item span New item
.modal-footer .modal-footer
button.btn.btn-outline-primary((click)='save()') Save button.btn.btn-outline-primary((click)='save()') Save
button.btn.btn-outline-danger((click)='cancel()') Cancel button.btn.btn-outline-danger((click)='cancel()') Cancel

@ -1,24 +1,11 @@
h3.mb-3 Appearance h3.mb-3 Appearance
.d-flex .d-flex
.mr-5 .mr-5
.form-line
.header
.title Frontend
.description Switches terminal frontend implementation (experimental)
select.form-control(
[(ngModel)]='config.store.terminal.frontend',
(ngModelChange)='config.save()',
)
option(value='hterm') hterm
option(value='xterm') xterm
option(value='xterm-webgl') xterm (WebGL)
.form-line .form-line
.header .header
.title Font .title Font
.d-flex.w-75 .input-group.w-75
input.form-control.w-75( input.form-control.w-75(
type='text', type='text',
[ngbTypeahead]='fontAutocomplete', [ngbTypeahead]='fontAutocomplete',
@ -52,9 +39,10 @@ h3.mb-3 Appearance
) )
option(*ngFor='let scheme of config.store.terminal.customColorSchemes', [ngValue]='scheme') Custom: {{scheme.name}} option(*ngFor='let scheme of config.store.terminal.customColorSchemes', [ngValue]='scheme') Custom: {{scheme.name}}
option(*ngFor='let scheme of colorSchemes', [ngValue]='scheme') {{scheme.name}} option(*ngFor='let scheme of colorSchemes', [ngValue]='scheme') {{scheme.name}}
.input-group-btn .input-group-append
button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)') Edit button.btn.btn-secondary((click)='editScheme(config.store.terminal.colorScheme)')
.input-group-btn i.fas.fa-pen
.input-group-append
button.btn.btn-outline-danger( button.btn.btn-outline-danger(
(click)='deleteScheme(config.store.terminal.colorScheme)', (click)='deleteScheme(config.store.terminal.colorScheme)',
*ngIf='isCustomScheme(config.store.terminal.colorScheme)' *ngIf='isCustomScheme(config.store.terminal.colorScheme)'
@ -65,10 +53,12 @@ h3.mb-3 Appearance
label Editing label Editing
.input-group .input-group
input.form-control(type='text', [(ngModel)]='editingColorScheme.name') input.form-control(type='text', [(ngModel)]='editingColorScheme.name')
.input-group-btn .input-group-append
button.btn.btn-secondary((click)='saveScheme()') Save button.btn.btn-secondary((click)='saveScheme()')
.input-group-btn i.fas.fa-check
button.btn.btn-secondary((click)='cancelEditing()') Cancel .input-group-append
button.btn.btn-secondary((click)='cancelEditing()')
i.fas.fa-times
.form-group(*ngIf='editingColorScheme') .form-group(*ngIf='editingColorScheme')
color-picker( color-picker(
@ -180,6 +170,19 @@ 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 Frontend
.description Switches terminal frontend implementation (experimental)
select.form-control(
[(ngModel)]='config.store.terminal.frontend',
(ngModelChange)='config.save()',
)
option(value='hterm') hterm
option(value='xterm') xterm
option(value='xterm-webgl') xterm (WebGL)
.form-line .form-line
.header .header
.title Terminal background .title Terminal background

@ -2,55 +2,55 @@
.form-group .form-group
label Name label Name
input.form-control( input.form-control(
type='text', type='text',
autofocus, autofocus,
[(ngModel)]='profile.name', [(ngModel)]='profile.name',
) )
.form-group .form-group
label Command label Command
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='profile.sessionOptions.command', [(ngModel)]='profile.sessionOptions.command',
) )
.form-group .form-group
label Arguments label Arguments
.input-group( .input-group(
*ngFor='let arg of profile.sessionOptions.args; index as i; trackBy: trackByIndex', *ngFor='let arg of profile.sessionOptions.args; index as i; trackBy: trackByIndex',
) )
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='profile.sessionOptions.args[i]', [(ngModel)]='profile.sessionOptions.args[i]',
) )
.input-group-btn .input-group-append
button.btn.btn-secondary((click)='profile.sessionOptions.args.splice(i, 1)') button.btn.btn-secondary((click)='profile.sessionOptions.args.splice(i, 1)')
i.fas.fa-trash i.fas.fa-trash
.mt-2 .mt-2
button.btn.btn-secondary((click)='profile.sessionOptions.args.push("")') button.btn.btn-secondary((click)='profile.sessionOptions.args.push("")')
i.fas.fa-plus.mr-2 i.fas.fa-plus.mr-2
| Add | Add
.form-line(*ngIf='uac.isAvailable') .form-line(*ngIf='uac.isAvailable')
.header .header
.title Run as administrator .title Run as administrator
toggle( toggle(
[(ngModel)]='profile.sessionOptions.runAsAdministrator', [(ngModel)]='profile.sessionOptions.runAsAdministrator',
) )
.form-group .form-group
label Working directory label Working directory
input.form-control( input.form-control(
type='text', type='text',
[(ngModel)]='profile.sessionOptions.cwd', [(ngModel)]='profile.sessionOptions.cwd',
) )
.form-group .form-group
label Environment label Environment
environment-editor( environment-editor(
type='text', type='text',
[(model)]='profile.sessionOptions.env', [(model)]='profile.sessionOptions.env',
) )
.modal-footer .modal-footer

@ -1,12 +1,13 @@
.mb-2.d-flex.align-items-center(*ngFor='let pair of vars') .mb-2.d-flex.align-items-center(*ngFor='let pair of vars')
.input-group.w-50 .input-group
input.form-control([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name') input.form-control.w-25([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name')
.input-group-append .input-group-append
.input-group-text = .input-group-text =
input.form-control.w-50.mr-1([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value') input.form-control.w-50([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value')
button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)') .input-group-append
i.fas.fa-trash button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
i.fas.fa-trash
button.btn.btn-secondary((click)='addEnvironmentVar()') button.btn.btn-secondary((click)='addEnvironmentVar()')
i.fas.fa-plus.mr-2 i.fas.fa-plus.mr-2
span Add span Add

@ -14,20 +14,20 @@ h3.mb-3 Shell
[ngValue]='slug(profile.name).toLowerCase()' [ngValue]='slug(profile.name).toLowerCase()'
) {{profile.name}} ) {{profile.name}}
.form-line(*ngIf='isConPTYAvailable') .form-line(*ngIf='isConPTYAvailable')
.header .header
.title Use ConPTY .title Use ConPTY
.description Enables the experimental Windows ConPTY API .description Enables the experimental Windows ConPTY API
toggle( toggle(
[(ngModel)]='config.store.terminal.useConPTY', [(ngModel)]='config.store.terminal.useConPTY',
(ngModelChange)='config.save()' (ngModelChange)='config.save()'
) )
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable') .alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable')
.mr-auto Windows 10 build 18309 or above is recommended for ConPTY .mr-auto Windows 10 build 18309 or above is recommended for ConPTY
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.profile.startsWith("WSL") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)') .alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.profile.startsWith("WSL") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)')
.mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend .mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend
@ -50,15 +50,17 @@ h3.mb-3 Shell
placeholder='Home directory', placeholder='Home directory',
[(ngModel)]='config.store.terminal.workingDirectory', [(ngModel)]='config.store.terminal.workingDirectory',
(ngModelChange)='config.save()', (ngModelChange)='config.save()',
) )
.input-group-btn .input-group-append
button.btn.btn-secondary((click)='pickWorkingDirectory()') button.btn.btn-secondary((click)='pickWorkingDirectory()')
i.fas.fa-folder-open i.fas.fa-folder-open
.form-line .form-line
.header .header
.title Always Use Working Directory .title Always Use Working Directory
.description By default, new terminals will open where the previous terminal was working. Enabling this option will always launch new terminals in the working directory specified above. .description
div By default, new terminals will open where the previous terminal was working.
div Enabling this option will always launch new terminals in the working directory specified above.
toggle( toggle(
[(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory', [(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory',
@ -69,7 +71,7 @@ h3.mb-3 Shell
.header .header
.title Environment .title Environment
.description Inject additional environment variables .description Inject additional environment variables
environment-editor([(model)]='this.config.store.terminal.environment') environment-editor([(model)]='this.config.store.terminal.environment')
h3.mt-3 Saved Profiles h3.mt-3 Saved Profiles
@ -78,16 +80,16 @@ h3.mt-3 Saved Profiles
.list-group-item.list-group-item-action.d-flex.align-items-center( .list-group-item.list-group-item-action.d-flex.align-items-center(
*ngFor='let profile of config.store.terminal.profiles', *ngFor='let profile of config.store.terminal.profiles',
(click)='editProfile(profile)', (click)='editProfile(profile)',
) )
.mr-auto .mr-auto
div {{profile.name}} div {{profile.name}}
.text-muted {{profile.sessionOptions.command}} .text-muted {{profile.sessionOptions.command}}
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)') button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
i.fas.fa-trash i.fas.fa-trash
div(ngbDropdown, placement='top-left') div(ngbDropdown, placement='top-left')
button.btn.btn-primary(ngbDropdownToggle) button.btn.btn-primary(ngbDropdownToggle)
i.fas.fa-fw.fa-plus i.fas.fa-fw.fa-plus
| New profile | New profile
div(ngbDropdownMenu) div(ngbDropdownMenu)
button.dropdown-item(*ngFor='let shell of shells', (click)='newProfile(shell)') {{shell.name}} button.dropdown-item(*ngFor='let shell of shells', (click)='newProfile(shell)') {{shell.name}}