From 19faa59446d04b1cadec02ee36d67fcb3e40c11a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Sun, 26 Mar 2017 20:32:05 -0700 Subject: [PATCH] theming - focus outline --- src/vs/base/browser/ui/button/button.css | 5 + src/vs/platform/theme/common/colorRegistry.ts | 9 +- .../activitybar/media/activitybarpart.css | 4 + .../browser/parts/editor/binaryEditor.ts | 1 + .../browser/parts/editor/media/tabstitle.css | 18 --- .../browser/parts/editor/tabsTitleControl.ts | 30 +++- .../electron-browser/media/shell.css | 153 +++--------------- src/vs/workbench/electron-browser/shell.ts | 19 ++- .../message/browser/media/messageList.css | 9 ++ 9 files changed, 97 insertions(+), 151 deletions(-) diff --git a/src/vs/base/browser/ui/button/button.css b/src/vs/base/browser/ui/button/button.css index e77131c5f4d..e4b7b582ccb 100644 --- a/src/vs/base/browser/ui/button/button.css +++ b/src/vs/base/browser/ui/button/button.css @@ -48,4 +48,9 @@ .vs-dark .monaco-button.monaco-text-button { background: #0E639C; +} + +.vs .monaco-text-button:focus, +.vs-dark .monaco-text-button:focus { + outline-color: rgba(255, 255, 255, .5); /* buttons have a blue color, so focus indication needs to be different */ } \ No newline at end of file diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts index b003e96af5f..6406aac5831 100644 --- a/src/vs/platform/theme/common/colorRegistry.ts +++ b/src/vs/platform/theme/common/colorRegistry.ts @@ -6,7 +6,7 @@ import platform = require('vs/platform/platform'); import { IJSONSchema } from 'vs/base/common/jsonSchema'; -import { Color } from 'vs/base/common/color'; +import { Color, RGBA } from 'vs/base/common/color'; import { ITheme } from 'vs/platform/theme/common/themeService'; import nls = require('vs/nls'); @@ -110,11 +110,14 @@ export function registerColor(id: string, defaults: ColorDefaults, description: return colorRegistry.registerColor(id, defaults, description); } - // ----- base colors export const foreground = registerColor('foreground', { dark: '#CCCCCC', light: '#6C6C6C', hc: '#FFFFFF' }, nls.localize('foreground', "Overall foreground color. This color is only used if not overridden by a component.")); -export const focus = registerColor('focus', { dark: '#007ACC', light: '#007ACC', hc: '#F38518' }, nls.localize('focus', "Overall outline/border color for focused elements. This color is only used if not overridden by a component.")); +export const focus = registerColor('focus', { + dark: Color.fromRGBA(new RGBA(14, 99, 156)).transparent(0.6), + light: Color.fromRGBA(new RGBA(0, 122, 204)).transparent(0.4), + hc: '#F38518' +}, nls.localize('focus', "Overall outline/border color for focused elements. This color is only used if not overridden by a component.")); /** * Commonly used High contrast colors. diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index 4482fe0d958..7acd81393fb 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -14,4 +14,8 @@ .monaco-workbench > .activitybar > .content .monaco-action-bar { text-align: left; background-color: inherit; +} + +.monaco-workbench > .activitybar [tabindex="0"]:focus { + outline: 0 !important; /* activity bar indicates focus custom */ } \ No newline at end of file diff --git a/src/vs/workbench/browser/parts/editor/binaryEditor.ts b/src/vs/workbench/browser/parts/editor/binaryEditor.ts index 3db818601c2..f2e1ec0cde6 100644 --- a/src/vs/workbench/browser/parts/editor/binaryEditor.ts +++ b/src/vs/workbench/browser/parts/editor/binaryEditor.ts @@ -55,6 +55,7 @@ export abstract class BaseBinaryResourceEditor extends BaseEditor { const binaryContainerElement = document.createElement('div'); binaryContainerElement.className = 'binary-container'; this.binaryContainer = $(binaryContainerElement); + this.binaryContainer.style('outline', 'none'); this.binaryContainer.tabindex(0); // enable focus support from the editor part (do not remove) // Custom Scrollbars diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitle.css b/src/vs/workbench/browser/parts/editor/media/tabstitle.css index 90a6c105bcb..15b2f88b2fd 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitle.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitle.css @@ -53,17 +53,6 @@ padding-right: 10px; } -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active:hover { - outline: 1px solid; - outline-offset: -5px; -} - -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab:hover { - outline: 1px dashed; - outline-offset: -5px; -} - /* Tab Label */ .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab .tab-label { @@ -135,13 +124,6 @@ background: url('close-inverse.svg') center center no-repeat; } -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active > .tab-close .action-label, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dirty > .tab-close .action-label, -.hc-black .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab:hover > .tab-close .action-label { - opacity: 1 !important; -} - /* No Tab Close Button */ .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.close-button-off { diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index ca8b92f44ac..159f2508d0a 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -40,7 +40,7 @@ import { extractResources } from 'vs/base/browser/dnd'; import { LinkedMap } from 'vs/base/common/map'; import { DelegatingWorkbenchEditorService } from 'vs/workbench/services/editor/browser/editorService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; -import { IThemeService } from 'vs/platform/theme/common/themeService'; +import { IThemeService, registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { INACTIVE_TAB_BACKGROUND, ACTIVE_TAB_BACKGROUND, ACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, ACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_ACTIVE_GROUP_FOREGROUND, INACTIVE_TAB_INACTIVE_GROUP_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; import { highContrastOutline } from 'vs/platform/theme/common/colorRegistry'; @@ -731,4 +731,30 @@ class TabActionRunner extends ActionRunner { return super.run(action, { group, editor: group.getEditor(this.index) }); } -} \ No newline at end of file +} + +registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { + + // High Contrast Styling + if (theme.type === 'hc') { + collector.addRule(` + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active, + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active:hover { + outline: 1px solid; + outline-offset: -5px; + } + + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab:hover { + outline: 1px dashed; + outline-offset: -5px; + } + + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active > .tab-close .action-label, + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab.dirty > .tab-close .action-label, + .monaco-workbench > .part.editor > .content > .one-editor-silo > .container > .title .tabs-container > .tab:hover > .tab-close .action-label { + opacity: 1 !important; + } + `); + } +}); \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/media/shell.css b/src/vs/workbench/electron-browser/media/shell.css index c678647bfbc..0cda2cc5bdc 100644 --- a/src/vs/workbench/electron-browser/media/shell.css +++ b/src/vs/workbench/electron-browser/media/shell.css @@ -66,21 +66,6 @@ cursor: pointer; } -/* START Keyboard Focus Indication Styles */ - -.monaco-shell.vs [tabindex="0"]:focus, -.monaco-shell.vs .synthetic-focus, -.monaco-shell.vs select:focus, -.monaco-shell.vs input[type="button"]:focus, -.monaco-shell.vs input[type="submit"]:focus, -.monaco-shell.vs input[type="search"]:focus, -.monaco-shell.vs input[type="text"]:focus, .monaco-shell.vs textarea:focus, -.monaco-shell.vs input[type="checkbox"]:focus { - outline: 1px solid; - outline-offset: -1px; - opacity: 1 !important; -} - .monaco-shell input[type="search"]::-webkit-search-decoration, .monaco-shell input[type="search"]::-webkit-search-results-button, .monaco-shell input[type="search"]::-webkit-search-results-decoration { @@ -96,15 +81,19 @@ background-position: center center; } -.monaco-shell.vs-dark [tabindex="0"]:focus, -.monaco-shell.vs-dark .synthetic-focus, -.monaco-shell.vs-dark select:focus, -.monaco-shell.vs-dark input[type="button"]:focus, -.monaco-shell.vs-dark input[type="submit"]:focus, -.monaco-shell.vs-dark input[type="search"]:focus, -.monaco-shell.vs-dark input[type="text"]:focus, .monaco-shell.vs-dark textarea:focus, -.monaco-shell.vs-dark input[type="checkbox"]:focus { - outline: 1px solid; +/* START Keyboard Focus Indication Styles */ + +.monaco-shell [tabindex="0"]:focus, +.monaco-shell .synthetic-focus, +.monaco-shell select:focus, +.monaco-shell input[type="button"]:focus, +.monaco-shell input[type="submit"]:focus, +.monaco-shell input[type="search"]:focus, +.monaco-shell input[type="text"]:focus, +.monaco-shell textarea:focus, +.monaco-shell input[type="checkbox"]:focus { + outline-width: 1px; + outline-style: solid; outline-offset: -1px; opacity: 1 !important; } @@ -113,32 +102,22 @@ .monaco-shell.hc-black .synthetic-focus, .monaco-shell.hc-black select:focus, .monaco-shell.hc-black input[type="button"]:focus, -.monaco-shell.hc-black input[type="text"]:focus, .monaco-shell.hc-black textarea:focus, +.monaco-shell.hc-black input[type="text"]:focus, +.monaco-shell.hc-black textarea:focus, .monaco-shell.hc-black input[type="search"]:focus, .monaco-shell.hc-black input[type="checkbox"]:focus { - outline: 2px solid; - outline-offset: -1px; -} - -.monaco-shell.vs .monaco-text-button:focus, -.monaco-shell.vs .action-button:focus { - outline-offset: -2px; /* Inset outline so it stands out on light background. */ -} - -.monaco-shell.hc-black .action-button:focus { - outline-offset: -4px; /* Helps high-contrast outline avoid clipping. */ + outline-style: solid; + outline-width: 2px; } .monaco-shell.hc-black .synthetic-focus input { background: transparent; /* Search input focus fix when in high contrast */ } -.monaco-shell.vs .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { - outline: 1px solid; /* higher contrast color for focusable elements in a row that shows focus feedback */ -} - +.monaco-shell.vs .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus, .monaco-shell.vs-dark .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { - outline: 1px solid; /* higher contrast color for focusable elements in a row that shows focus feedback */ + outline-width: 1px; /* higher contrast color for focusable elements in a row that shows focus feedback */ + outline-style: solid; } .monaco-shell .monaco-tree.focused.no-focused-item:focus:before { @@ -150,20 +129,14 @@ z-index: 5; /* make sure we are on top of the tree items */ content: ""; pointer-events: none; /* enable click through */ -} - -.monaco-shell.vs .monaco-tree.focused.no-focused-item:focus:before { - outline: 1px solid; /* we still need to handle the empty tree or no focus item case */ - outline-offset: -1px; -} - -.monaco-shell.vs-dark .monaco-tree.focused.no-focused-item:focus:before { outline: 1px solid; /* we still need to handle the empty tree or no focus item case */ + outline-width: 1px; + outline-style: solid; outline-offset: -1px; } .monaco-shell.hc-black .monaco-tree.focused.no-focused-item:focus:before { - outline: 2px solid; /* we still need to handle the empty tree or no focus item case */ + outline-width: 2px; outline-offset: -2px; } @@ -189,82 +162,8 @@ .monaco-shell input[type="button"]:active, .monaco-shell input[type="submit"]:active, .monaco-shell input[type="checkbox"]:active, -.monaco-shell .monaco-tree .monaco-tree-row .monaco-action-bar .action-item [tabindex="0"]:hover, +.monaco-shell .monaco-tree .monaco-tree-row +.monaco-action-bar .action-item [tabindex="0"]:hover, .monaco-shell .monaco-tree.focused.no-focused-item:active:before { outline: 0 !important; /* fixes some flashing outlines from showing up when clicking */ -} - -.monaco-shell .activitybar [tabindex="0"]:focus { - outline: 0 !important; /* activity bar indicates focus custom */ -} - -.monaco-shell .part.editor .binary-container { - outline: 0 !important; -} - -/* END Keyboard Focus Indication Styles */ - -/* TODO@theme (widgets) */ - -/* START Keyboard Focus Indication Styles */ - -.monaco-shell.vs [tabindex="0"]:focus, -.monaco-shell.vs .synthetic-focus, -.monaco-shell.vs select:focus, -.monaco-shell.vs input[type="button"]:focus, -.monaco-shell.vs input[type="submit"]:focus, -.monaco-shell.vs input[type="search"]:focus, -.monaco-shell.vs input[type="text"]:focus, .monaco-shell.vs textarea:focus, -.monaco-shell.vs input[type="checkbox"]:focus { - outline-color: rgba(0, 122, 204, 0.4); -} - -.monaco-shell.vs-dark [tabindex="0"]:focus, -.monaco-shell.vs-dark .synthetic-focus, -.monaco-shell.vs-dark select:focus, -.monaco-shell.vs-dark input[type="button"]:focus, -.monaco-shell.vs-dark input[type="submit"]:focus, -.monaco-shell.vs-dark input[type="search"]:focus, -.monaco-shell.vs-dark input[type="text"]:focus, .monaco-shell.vs-dark textarea:focus, -.monaco-shell.vs-dark input[type="checkbox"]:focus { - outline-color: rgba(14, 99, 156, 0.6); -} - -.monaco-shell.hc-black [tabindex="0"]:focus, -.monaco-shell.hc-black .synthetic-focus, -.monaco-shell.hc-black select:focus, -.monaco-shell.hc-black input[type="button"]:focus, -.monaco-shell.hc-black input[type="text"]:focus, .monaco-shell.hc-black textarea:focus, -.monaco-shell.hc-black input[type="search"]:focus, -.monaco-shell.hc-black input[type="checkbox"]:focus { - outline-color: #f38518; -} - -.monaco-shell.vs .monaco-text-button:focus, -.monaco-shell.vs-dark .monaco-text-button:focus, -.monaco-shell.vs .action-button:focus, -.monaco-shell.vs-dark .action-button:focus { - outline-color: rgba(255, 255, 255, .5); /* buttons have a blue color, so focus indication needs to be different */ -} - -.monaco-shell.vs .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { - outline-color: #007ACC; /* higher contrast color for focusable elements in a row that shows focus feedback */ -} - -.monaco-shell.vs-dark .monaco-tree.focused .monaco-tree-row.focused [tabindex="0"]:focus { - outline-color: #007ACC; /* higher contrast color for focusable elements in a row that shows focus feedback */ -} - -.monaco-shell.vs .monaco-tree.focused.no-focused-item:focus:before { - outline-color: rgba(0, 122, 204, 0.4); /* we still need to handle the empty tree or no focus item case */ -} - -.monaco-shell.vs-dark .monaco-tree.focused.no-focused-item:focus:before { - outline-color: rgba(14, 99, 156, 0.6); /* we still need to handle the empty tree or no focus item case */ -} - -.monaco-shell.hc-black .monaco-tree.focused.no-focused-item:focus:before { - outline-color: #f38518; /* we still need to handle the empty tree or no focus item case */ -} - -/* END Keyboard Focus Indication Styles */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index b8fa88a1647..db718c527b0 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -104,7 +104,7 @@ import 'vs/platform/opener/browser/opener.contribution'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService'; import { registerThemingParticipant, ITheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; -import { foreground } from 'vs/platform/theme/common/colorRegistry'; +import { foreground, focus } from 'vs/platform/theme/common/colorRegistry'; /** * Services that we require for the Shell @@ -517,4 +517,21 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { if (windowForeground) { collector.addRule(`.monaco-shell { color: ${windowForeground}; }`); } + + const focusOutline = theme.getColor(focus); + if (focusOutline) { + collector.addRule(` + .monaco-shell [tabindex="0"]:focus, + .monaco-shell .synthetic-focus, + .monaco-shell select:focus, + .monaco-shell .monaco-tree.focused.no-focused-item:focus:before, + .monaco-shell input[type="button"]:focus, + .monaco-shell input[type="text"]:focus, + .monaco-shell textarea:focus, + .monaco-shell input[type="search"]:focus, + .monaco-shell input[type="checkbox"]:focus { + outline-color: ${focusOutline}; + } + `); + } }); \ No newline at end of file diff --git a/src/vs/workbench/services/message/browser/media/messageList.css b/src/vs/workbench/services/message/browser/media/messageList.css index dd2f9d08b0d..617ce39b8db 100644 --- a/src/vs/workbench/services/message/browser/media/messageList.css +++ b/src/vs/workbench/services/message/browser/media/messageList.css @@ -105,6 +105,10 @@ border: 1px solid; } +.hc-black .global-message-list li.message-list-entry .actions-container .message-action .action-button:focus { + outline-offset: -4px; /* Helps high-contrast outline avoid clipping. */ +} + /* TODO@theme */ .vs .global-message-list, @@ -142,6 +146,11 @@ border-color: #6FC3DF; } +.vs .global-message-list li.message-list-entry .actions-container .message-action .action-button:focus, +.vs-dark .global-message-list li.message-list-entry .actions-container .message-action .action-button:focus { + outline-color: rgba(255, 255, 255, .5); /* buttons have a blue color, so focus indication needs to be different */ +} + .vs .global-message-list li.message-list-entry .message-left-side.severity.app-error { background-color: #BE1100; } -- GitLab