mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Use document-style for Notebooks (#3902)
* Added hover support, adding box shadow and light outline on hovering and the "more actions" button showing on hover * Added box shadow for dark themes (hooray!) * Remove border from everything but the code cell unless a cell is selected or hovered over. This ensures this looks like a document * Fix high contrast theming issues.
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div style="width: 100%; height: 100%; display: flex; flex-flow: row">
|
<div style="width: 100%; height: 100%; display: flex; flex-flow: row" (mouseover)="hover=true" (mouseleave)="hover=false">
|
||||||
<div #toolbar class="toolbar" style="flex: 0 0 auto; display: flex; flex-flow:column; width: 40px; min-height: 40px; orientation: portrait">
|
<div #toolbar class="toolbar" style="flex: 0 0 auto; display: flex; flex-flow:column; width: 40px; min-height: 40px; orientation: portrait">
|
||||||
</div>
|
</div>
|
||||||
<div #editor class="editor" style="flex: 1 1 auto; overflow: hidden;">
|
<div #editor class="editor" style="flex: 1 1 auto; overflow: hidden;">
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
|
|||||||
this._activeCellId = value;
|
this._activeCellId = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Input() set hover(value: boolean) {
|
||||||
|
this._hover = value;
|
||||||
|
if (!this.isActive()) {
|
||||||
|
// Only make a change if we're not active, since this has priority
|
||||||
|
this.toggleMoreActionsButton(this._hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected _actionBar: Taskbar;
|
protected _actionBar: Taskbar;
|
||||||
private readonly _minimumHeight = 30;
|
private readonly _minimumHeight = 30;
|
||||||
private _editor: QueryTextEditor;
|
private _editor: QueryTextEditor;
|
||||||
@@ -63,6 +72,7 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
|
|||||||
private _model: NotebookModel;
|
private _model: NotebookModel;
|
||||||
private _activeCellId: string;
|
private _activeCellId: string;
|
||||||
private _cellToggleMoreActions: CellToggleMoreActions;
|
private _cellToggleMoreActions: CellToggleMoreActions;
|
||||||
|
private _hover: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
|
||||||
@@ -202,4 +212,12 @@ export class CodeComponent extends AngularDisposable implements OnInit, OnChange
|
|||||||
this._editor.getContainer().scrollIntoView();
|
this._editor.getContainer().scrollIntoView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isActive() {
|
||||||
|
return this.cellModel && this.cellModel.id === this.activeCellId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected toggleMoreActionsButton(isActive: boolean) {
|
||||||
|
this._cellToggleMoreActions.toggle(isActive, this.moreActionsElementRef, this.model, this.cellModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div style="width: 100%; height: 100%; display: flex; flex-flow: column">
|
<div style="width: 100%; height: 100%; display: flex; flex-flow: column">
|
||||||
<div class="notebook-code" style="flex: 0 0 auto;">
|
<div style="flex: 0 0 auto;">
|
||||||
<code-component [cellModel]="cellModel" [model]="model" [activeCellId]="activeCellId"></code-component>
|
<code-component [cellModel]="cellModel" [model]="model" [activeCellId]="activeCellId"></code-component>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex: 0 0 auto; width: 100%; height: 100%; display: block">
|
<div style="flex: 0 0 auto; width: 100%; height: 100%; display: block">
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ output-area-component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output-area-component .notebook-output {
|
output-area-component .notebook-output {
|
||||||
border-top-width: 1px;
|
border-top-width: 0px;
|
||||||
border-top-style: solid;
|
|
||||||
user-select: initial;
|
user-select: initial;
|
||||||
padding: 5px 20px 0px;
|
padding: 5px 20px 0px;
|
||||||
box-shadow: rgba(120, 120, 120, 0.75) 0px -2px 1px -2px;
|
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
|
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column" (mouseover)="hover=true" (mouseleave)="hover=false">
|
||||||
<loading-spinner [loading]="isLoading"></loading-spinner>
|
<loading-spinner [loading]="isLoading"></loading-spinner>
|
||||||
<div class="notebook-text" style="flex: 0 0 auto;">
|
<div class="notebook-text" style="flex: 0 0 auto;">
|
||||||
<code-component *ngIf="isEditMode" [cellModel]="cellModel" (onContentChanged)="handleContentChanged()" [model]="model" [activeCellId]="activeCellId" [hideVerticalToolbar]=true>
|
<code-component *ngIf="isEditMode" [cellModel]="cellModel" (onContentChanged)="handleContentChanged()" [model]="model" [activeCellId]="activeCellId" [hideVerticalToolbar]=true>
|
||||||
|
|||||||
@@ -41,6 +41,14 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
|||||||
this._activeCellId = value;
|
this._activeCellId = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Input() set hover(value: boolean) {
|
||||||
|
this._hover = value;
|
||||||
|
if (!this.isActive()) {
|
||||||
|
// Only make a change if we're not active, since this has priority
|
||||||
|
this.updateMoreActions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _content: string;
|
private _content: string;
|
||||||
private isEditMode: boolean;
|
private isEditMode: boolean;
|
||||||
private _sanitizer: ISanitizer;
|
private _sanitizer: ISanitizer;
|
||||||
@@ -50,6 +58,7 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
|||||||
public readonly onDidClickLink = this._onDidClickLink.event;
|
public readonly onDidClickLink = this._onDidClickLink.event;
|
||||||
protected isLoading: boolean;
|
protected isLoading: boolean;
|
||||||
private _cellToggleMoreActions: CellToggleMoreActions;
|
private _cellToggleMoreActions: CellToggleMoreActions;
|
||||||
|
private _hover: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _bootstrapService: CommonServiceInterface,
|
||||||
@@ -158,24 +167,33 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
|||||||
|
|
||||||
public toggleEditMode(editMode?: boolean): void {
|
public toggleEditMode(editMode?: boolean): void {
|
||||||
this.isEditMode = editMode !== undefined? editMode : !this.isEditMode;
|
this.isEditMode = editMode !== undefined? editMode : !this.isEditMode;
|
||||||
if (!this.isEditMode && this.cellModel.id === this._activeCellId) {
|
this.updateMoreActions();
|
||||||
this._cellToggleMoreActions.toggle(true, this.moreActionsElementRef, this.model, this.cellModel);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._cellToggleMoreActions.toggle(false, this.moreActionsElementRef, this.model, this.cellModel);
|
|
||||||
}
|
|
||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
this._changeRef.detectChanges();
|
this._changeRef.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private setFocusAndScroll(): void {
|
private updateMoreActions(): void {
|
||||||
if (this.cellModel.id === this._activeCellId) {
|
if (!this.isEditMode && (this.isActive() || this._hover)) {
|
||||||
this.toggleEditMode(true);
|
this.toggleMoreActionsButton(true);
|
||||||
} else {
|
|
||||||
this.toggleEditMode(false);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.toggleMoreActionsButton(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private setFocusAndScroll(): void {
|
||||||
|
this.toggleEditMode(this.isActive());
|
||||||
|
|
||||||
if (this.output && this.output.nativeElement) {
|
if (this.output && this.output.nativeElement) {
|
||||||
(<HTMLElement>this.output.nativeElement).scrollTo();
|
(<HTMLElement>this.output.nativeElement).scrollTo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected isActive() {
|
||||||
|
return this.cellModel && this.cellModel.id === this.activeCellId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected toggleMoreActionsButton(isActive: boolean) {
|
||||||
|
this._cellToggleMoreActions.toggle(isActive, this.moreActionsElementRef, this.model, this.cellModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,6 @@ text-cell-component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
text-cell-component .notebook-preview {
|
text-cell-component .notebook-preview {
|
||||||
border-top-width: 1px;
|
|
||||||
border-top-style: solid;
|
|
||||||
user-select: initial;
|
user-select: initial;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import 'vs/css!./notebook';
|
|||||||
|
|
||||||
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
|
||||||
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||||
import { activeContrastBorder, buttonBackground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
import { activeContrastBorder, contrastBorder, buttonBackground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||||
|
|
||||||
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||||
|
|
||||||
|
let lightBoxShadow = '0px 4px 6px 0px rgba(0,0,0,0.14)';
|
||||||
|
let darkBoxShadow = '0 4px 6px 0px rgba(0, 0, 0, 1)';
|
||||||
// Active border
|
// Active border
|
||||||
const activeBorder = theme.getColor(buttonBackground);
|
const activeBorder = theme.getColor(buttonBackground);
|
||||||
if (activeBorder) {
|
if (activeBorder) {
|
||||||
@@ -17,17 +19,64 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
.notebookEditor .notebook-cell.active {
|
.notebookEditor .notebook-cell.active {
|
||||||
border-color: ${activeBorder};
|
border-color: ${activeBorder};
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
box-shadow: 0px 4px 6px 0px rgba(0,0,0,0.14);
|
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Box shadow handling
|
||||||
|
collector.addRule(`
|
||||||
|
.notebookEditor .notebook-cell.active {
|
||||||
|
box-shadow: ${lightBoxShadow};
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .notebookEditor .notebook-cell.active {
|
||||||
|
box-shadow: ${darkBoxShadow};
|
||||||
|
}
|
||||||
|
|
||||||
|
.hc-black .notebookEditor .notebook-cell.active {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebookEditor .notebook-cell:hover:not(.active) {
|
||||||
|
box-shadow: ${lightBoxShadow};
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .notebookEditor .notebook-cell:hover:not(.active) {
|
||||||
|
box-shadow: ${darkBoxShadow};
|
||||||
|
}
|
||||||
|
|
||||||
|
.hc-black .notebookEditor .notebook-cell:hover:not(.active) {
|
||||||
|
box-shadow: 0;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
|
||||||
// Inactive border
|
// Inactive border
|
||||||
const inactiveBorder = theme.getColor(SIDE_BAR_BACKGROUND);
|
const inactiveBorder = theme.getColor(SIDE_BAR_BACKGROUND);
|
||||||
if (inactiveBorder) {
|
if (inactiveBorder) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
|
.notebookEditor .notebook-cell code-component {
|
||||||
|
border-color: ${inactiveBorder};
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-radius: 3px 3px 3px 3px;
|
||||||
|
}
|
||||||
|
.notebookEditor .notebook-cell.active code-component {
|
||||||
|
border-width: 0px 0px 1px 0px;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
.notebookEditor .notebook-cell:hover code-component {
|
||||||
|
border-width: 0px 0px 1px 0px;
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
.notebookEditor .notebook-cell {
|
.notebookEditor .notebook-cell {
|
||||||
border-color: ${inactiveBorder};
|
border-color: ${inactiveBorder};
|
||||||
|
border-width: 0px;
|
||||||
|
}
|
||||||
|
.notebookEditor .notebook-cell.active {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
.notebookEditor .notebook-cell:hover {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -41,17 +90,27 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
|
|
||||||
// Styling with Outline color (e.g. high contrast theme)
|
// Styling with Outline color (e.g. high contrast theme)
|
||||||
const outline = theme.getColor(activeContrastBorder);
|
const outline = theme.getColor(activeContrastBorder);
|
||||||
|
const hcOutline = theme.getColor(contrastBorder);
|
||||||
if (outline) {
|
if (outline) {
|
||||||
collector.addRule(`
|
collector.addRule(`
|
||||||
|
.hc-black .notebookEditor .notebook-cell:not(.active) code-component {
|
||||||
|
border-color: ${hcOutline};
|
||||||
|
border-width: 0px 0px 1px 0px;
|
||||||
|
}
|
||||||
|
.hc-black .notebookEditor .notebook-cell.active code-component {
|
||||||
|
border-color: ${outline};
|
||||||
|
border-width: 0px 0px 1px 0px;
|
||||||
|
}
|
||||||
|
.hc-black .notebookEditor .notebook-cell:not(.active) {
|
||||||
|
outline-color: ${hcOutline};
|
||||||
|
outline-width: 1px;
|
||||||
|
outline-style: solid;
|
||||||
|
}
|
||||||
.notebookEditor .notebook-cell.active {
|
.notebookEditor .notebook-cell.active {
|
||||||
outline-color: ${outline};
|
outline-color: ${outline};
|
||||||
outline-width: 1px;
|
outline-width: 1px;
|
||||||
outline-style: solid;
|
outline-style: solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notebookEditor .notebook-cell:hover:not(.active) {
|
|
||||||
outline-style: dashed;
|
|
||||||
}
|
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user