diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 157a1e549..ebcec00a1 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -18,6 +18,7 @@ require.paths.unshift(fixturePackagesPath) [bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = [] beforeEach -> + jQuery.fx.off = true window.fixturesProject = new Project(require.resolve('fixtures')) window.resetTimeouts() atom.atomPackageStates = {} diff --git a/src/packages/command-panel/keymaps/command-panel.cson b/src/packages/command-panel/keymaps/command-panel.cson index 90b1d19fa..8fb5a304e 100644 --- a/src/packages/command-panel/keymaps/command-panel.cson +++ b/src/packages/command-panel/keymaps/command-panel.cson @@ -12,3 +12,13 @@ 'meta-e': 'command-panel:set-selection-as-regex-address' 'meta-f': 'command-panel:find-in-file' 'meta-F': 'command-panel:find-in-project' + +'.command-panel': + 'ctrl-{': 'command-panel:collapse-all' + 'ctrl-}': 'command-panel:expand-all' + +'.command-panel .preview-list': + 'left': 'command-panel:collapse-result' + 'ctrl-[': 'command-panel:collapse-result' + 'right': 'command-panel:expand-result' + 'ctrl-]': 'command-panel:expand-result' diff --git a/src/packages/command-panel/lib/command-panel-view.coffee b/src/packages/command-panel/lib/command-panel-view.coffee index bf6a5c225..24b9dd60f 100644 --- a/src/packages/command-panel/lib/command-panel-view.coffee +++ b/src/packages/command-panel/lib/command-panel-view.coffee @@ -11,7 +11,13 @@ module.exports = class CommandPanelView extends View @content: -> @div class: 'command-panel tool-panel', => - @div outlet: 'previewCount', class: 'preview-count' + @div class: 'loading', outlet: 'loadingMessage' + @div class: 'header', outlet: 'previewHeader', => + @ul outlet: 'expandCollapse', class: 'expand-collapse', => + @li class: 'expand', 'Expand All' + @li class: 'collapse', 'Collapse All' + @span outlet: 'previewCount', class: 'preview-count' + @subview 'previewList', new PreviewList(rootView) @ul class: 'error-messages', outlet: 'errorMessages' @div class: 'prompt-and-editor', => @@ -40,8 +46,11 @@ class CommandPanelView extends View rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse() rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress() + @on 'click', '.expand', @onExpandAll + @on 'click', '.collapse', @onCollapseAll + @previewList.hide() - @previewCount.hide() + @previewHeader.hide() @errorMessages.hide() @prompt.iconSize(@miniEditor.getFontSize()) @@ -66,17 +75,35 @@ class CommandPanelView extends View togglePreview: -> if @previewList.is(':focus') @previewList.hide() - @previewCount.hide() + @previewHeader.hide() @detach() rootView.focus() else @attach() unless @hasParent() if @previewList.hasOperations() @previewList.show().focus() - @previewCount.show() + @previewHeader.show() else @miniEditor.focus() + toggleLoading: -> + if @loadingMessage.hasClass 'is-loading' + @loadingMessage.removeClass 'is-loading' + @loadingMessage.html '' + @loadingMessage.hide() + else + @loadingMessage.addClass 'is-loading' + @loadingMessage.html 'Searching...' + @loadingMessage.show() + + onExpandAll: (event) => + @previewList.expandAllPaths() + @previewList.focus() + + onCollapseAll: (event) => + @previewList.collapseAllPaths() + @previewList.focus() + attach: (text='', options={}) -> @errorMessages.hide() @@ -89,17 +116,19 @@ class CommandPanelView extends View detach: -> rootView.focus() @previewList.hide() - @previewCount.hide() + @previewHeader.hide() super escapedCommand: -> @miniEditor.getText() execute: (command=@escapedCommand())-> + @toggleLoading() @errorMessages.empty() try @commandInterpreter.eval(command, rootView.getActiveEditSession()).done ({operationsToPreview, errorMessages}) => + @toggleLoading() @history.push(command) @historyIndex = @history.length @@ -109,6 +138,7 @@ class CommandPanelView extends View @errorMessages.append $$ -> @li errorMessage for errorMessage in errorMessages else if operationsToPreview?.length + @previewHeader.show() @previewList.populate(operationsToPreview) @previewList.focus() @previewCount.text("#{_.pluralize(operationsToPreview.length, 'match', 'matches')} in #{_.pluralize(@previewList.getPathCount(), 'file')}").show() diff --git a/src/packages/command-panel/lib/operation-view.coffee b/src/packages/command-panel/lib/operation-view.coffee new file mode 100644 index 000000000..2655a4fba --- /dev/null +++ b/src/packages/command-panel/lib/operation-view.coffee @@ -0,0 +1,28 @@ +{View} = require 'space-pen' + +module.exports = +class OperationView extends View + @content: ({operation} = {}) -> + {prefix, suffix, match, range} = operation.preview() + @li 'data-index': operation.index, class: 'operation', => + @span range.start.row + 1, class: 'line-number' + @span class: 'preview', => + @span prefix + @span match, class: 'match' + @span suffix + + initialize: ({@previewList, @operation}) -> + @subscribe @previewList, 'core:confirm', => + if @hasClass('selected') + @executeOperation() + false + @on 'mousedown', (e) => + @executeOperation() + @previewList.find('.selected').removeClass('selected') + @addClass('selected') + + executeOperation: -> + editSession = rootView.open(@operation.getPath()) + bufferRange = @operation.execute(editSession) + editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange + @previewList.focus() diff --git a/src/packages/command-panel/lib/path-view.coffee b/src/packages/command-panel/lib/path-view.coffee new file mode 100644 index 000000000..b4f2ba151 --- /dev/null +++ b/src/packages/command-panel/lib/path-view.coffee @@ -0,0 +1,58 @@ +{View} = require 'space-pen' +fs = require 'fs' +OperationView = require './operation-view' +$ = require 'jquery' + +module.exports = +class PathView extends View + @content: ({path, operations, previewList} = {}) -> + classes = ['path'] + classes.push('readme') if fs.isReadmePath(path) + @li class: classes.join(' '), => + @div outlet: 'pathDetails', class: 'path-details', => + @span class: 'path-name', path + @span "(#{operations.length})", class: 'path-match-number' + @ul outlet: 'matches', class: 'matches', => + for operation in operations + @subview "operation#{operation.index}", new OperationView({operation, previewList}) + + initialize: ({@previewList}) -> + @pathDetails.on 'mousedown', => @toggle(true) + @subscribe @previewList, 'command-panel:collapse-result', => + @collapse(true) if @isSelected() + @subscribe @previewList, 'command-panel:expand-result', => + @expand(true) if @isSelected() + @subscribe @previewList, 'core:confirm', => + if @hasClass('selected') + @toggle(true) + false + + isSelected: -> + @hasClass('selected') or @find('.selected').length + + setSelected: -> + @previewList.find('.selected').removeClass('selected') + @addClass('selected') + + toggle: (animate) -> + if @hasClass('is-collapsed') + @expand(animate) + else + @collapse(animate) + + expand: (animate=false) -> + if animate + @matches.show 100, => @removeClass 'is-collapsed' + else + @matches.show() + @removeClass 'is-collapsed' + + collapse: (animate=false) -> + if animate + @matches.hide 100, => + @addClass 'is-collapsed' + @setSelected() if @isSelected() + else + @matches.hide() + @addClass 'is-collapsed' + @setSelected() if @isSelected() diff --git a/src/packages/command-panel/lib/preview-list.coffee b/src/packages/command-panel/lib/preview-list.coffee index f496f7509..908b28971 100644 --- a/src/packages/command-panel/lib/preview-list.coffee +++ b/src/packages/command-panel/lib/preview-list.coffee @@ -3,24 +3,30 @@ $ = require 'jquery' ScrollView = require 'scroll-view' _ = require 'underscore' fs = require 'fs' +PathView = require './path-view' +OperationView = require './operation-view' module.exports = class PreviewList extends ScrollView @content: -> - @ol class: 'preview-list', tabindex: -1, -> + @ol class: 'preview-list', tabindex: -1 - selectedOperationIndex: 0 operations: null - initialize: (@rootView) -> + initialize: -> super + @on 'core:move-down', => @selectNextOperation(); false @on 'core:move-up', => @selectPreviousOperation(); false - @on 'core:confirm', => @executeSelectedOperation() - @on 'mousedown', 'li.operation', (e) => - @setSelectedOperationIndex(parseInt($(e.target).closest('li').data('index'))) - @executeSelectedOperation() + @command 'command-panel:collapse-all', => @collapseAllPaths() + @command 'command-panel:expand-all', => @expandAllPaths() + + expandAllPaths: -> + @children().each (index, element) -> $(element).view().expand() + + collapseAllPaths: -> + @children().each (index, element) -> $(element).view().collapse() destroy: -> @destroyOperations() if @operations @@ -31,26 +37,14 @@ class PreviewList extends ScrollView @destroyOperations() if @operations @operations = operations @empty() - @html $$$ -> - operation.index = index for operation, index in operations - operationsByPath = _.groupBy(operations, (operation) -> operation.getPath()) - for path, ops of operationsByPath - classes = ['path'] - classes.push('readme') if fs.isReadmePath(path) - @li class: classes.join(' '), => - @span path - @span "(#{ops.length})", class: 'path-match-number' - for operation in ops - {prefix, suffix, match, range} = operation.preview() - @li 'data-index': operation.index, class: 'operation', => - @span range.start.row + 1, class: 'line-number' - @span class: 'preview', => - @span prefix - @span match, class: 'match' - @span suffix - @setSelectedOperationIndex(0) + operation.index = index for operation, index in operations + operationsByPath = _.groupBy(operations, (operation) -> operation.getPath()) + for path, operations of operationsByPath + @append new PathView({path, operations, previewList: this}) + @show() + @find('.operation:first').addClass('selected') @setLineNumberWidth() setLineNumberWidth: -> @@ -61,33 +55,33 @@ class PreviewList extends ScrollView lineNumbers.width(maxWidth) selectNextOperation: -> - @setSelectedOperationIndex(@selectedOperationIndex + 1) + selectedView = @find('.selected').view() + + if selectedView instanceof PathView + if selectedView.hasClass('is-collapsed') + nextView = selectedView.next().view() + else + nextView = selectedView.find('.operation:first') + else + nextView = selectedView.next().view() ? selectedView.closest('.path').next().view() + if nextView? + selectedView.removeClass('selected') + nextView.addClass('selected') + @scrollToElement(nextView) selectPreviousOperation: -> - @setSelectedOperationIndex(@selectedOperationIndex - 1) + selectedView = @find('.selected').view() - setSelectedOperationIndex: (index, scrollToOperation=true) -> - index = Math.max(0, index) - index = Math.min(@operations.length - 1, index) - @children(".selected").removeClass('selected') - element = @children("li.operation:eq(#{index})") - element.addClass('selected') + if selectedView instanceof PathView + previousView = selectedView.prev() + previousView = previousView.find('.operation:last').view() unless previousView.hasClass('is-collapsed') + else + previousView = selectedView.prev().view() ? selectedView.closest('.path').view() - if scrollToOperation - if index is 0 - @scrollToTop() - else - @scrollToElement(element) - - @selectedOperationIndex = index - - executeSelectedOperation: -> - operation = @getSelectedOperation() - editSession = @rootView.open(operation.getPath()) - bufferRange = operation.execute(editSession) - editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange - @focus() - false + if previousView? + selectedView.removeClass('selected') + previousView.addClass('selected') + @scrollToElement(previousView) getPathCount: -> _.keys(_.groupBy(@operations, (operation) -> operation.getPath())).length @@ -100,23 +94,27 @@ class PreviewList extends ScrollView @operations = null getSelectedOperation: -> - @operations[@selectedOperationIndex] + @find('.operation.selected').view()?.operation scrollToElement: (element) -> - top = @scrollTop() + element.position().top + top = @scrollTop() + element.offset().top - @offset().top bottom = top + element.outerHeight() - if bottom > @scrollBottom() - @scrollBottom(bottom) - if top < @scrollTop() - @scrollTop(top) + @scrollBottom(bottom) if bottom > @scrollBottom() + @scrollTop(top) if top < @scrollTop() scrollToBottom: -> super() - @setSelectedOperationIndex(Infinity, false) + @find('.selected').removeClass('selected') + lastPath = @find('.path:last') + if lastPath.hasClass('is-collapsed') + lastPath.addClass('selected') + else + lastPath.find('.operation:last').addClass('selected') scrollToTop: -> super() - @setSelectedOperationIndex(0, false) + @find('.selected').removeClass('selected') + @find('.path:first').addClass('selected') diff --git a/src/packages/command-panel/spec/command-panel-spec.coffee b/src/packages/command-panel/spec/command-panel-spec.coffee index 253bd0662..c130492a9 100644 --- a/src/packages/command-panel/spec/command-panel-spec.coffee +++ b/src/packages/command-panel/spec/command-panel-spec.coffee @@ -128,6 +128,9 @@ describe "CommandPanel", -> beforeEach -> expect(commandPanel.previewList).toBeVisible() + it "shows the expand and collapse all buttons", -> + expect(commandPanel.find('.expand-collapse')).toBeVisible() + describe "when the preview list is focused", -> it "hides the command panel", -> expect(commandPanel.previewList).toMatchSelector(':focus') @@ -171,19 +174,19 @@ describe "CommandPanel", -> expect(commandPanel.hasParent()).toBeTruthy() describe "when the mini editor is focused", -> - it "retains focus on the mini editor and does not show the preview list or preview count", -> + it "retains focus on the mini editor and does not show the preview list or preview header", -> expect(commandPanel.miniEditor.isFocused).toBeTruthy() rootView.trigger 'command-panel:toggle-preview' expect(commandPanel.previewList).toBeHidden() - expect(commandPanel.previewCount).toBeHidden() + expect(commandPanel.previewHeader).toBeHidden() expect(commandPanel.miniEditor.isFocused).toBeTruthy() describe "when the mini editor is not focused", -> - it "focuses the mini editor and does not show the preview list or preview count", -> + it "focuses the mini editor and does not show the preview list or preview header", -> rootView.focus() rootView.trigger 'command-panel:toggle-preview' expect(commandPanel.previewList).toBeHidden() - expect(commandPanel.previewCount).toBeHidden() + expect(commandPanel.previewHeader).toBeHidden() expect(commandPanel.miniEditor.isFocused).toBeTruthy() describe "when the command panel is not visible", -> @@ -290,7 +293,7 @@ describe "CommandPanel", -> expect(commandPanel.previewList).toBeVisible() expect(commandPanel.previewList).toMatchSelector ':focus' previewItem = commandPanel.previewList.find("li:contains(sample.js):first") - expect(previewItem.text()).toBe "sample.js(1)" + expect(previewItem.find('.path-details').text()).toBe "sample.js(1)" expect(previewItem.next().find('.preview').text()).toBe "var quicksort = function () {" expect(previewItem.next().find('.preview > .match').text()).toBe "quicksort" @@ -392,29 +395,38 @@ describe "CommandPanel", -> expect(previewList.find('li.operation:eq(1)')).toHaveClass 'selected' expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1] - _.times previewList.getOperations().length - 2, -> previewList.trigger 'core:move-down' + _.times previewList.getOperations().length + previewList.getPathCount(), -> previewList.trigger 'core:move-down' expect(previewList.find("li.operation:last")).toHaveClass 'selected' expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations()) expect(previewList.scrollBottom()).toBeCloseTo previewList.prop('scrollHeight'), -1 - _.times previewList.getOperations().length, -> previewList.trigger 'core:move-up' + _.times previewList.getOperations().length + previewList.getPathCount(), -> previewList.trigger 'core:move-up' expect(previewList.scrollTop()).toBe 0 it "doesn't bubble up the event and the command panel text doesn't change", -> rootView.attachToDom() commandPanel.miniEditor.setText "command" previewList.focus() - previewList.trigger 'core:move-up' - expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' - expect(commandPanel.miniEditor.getText()).toBe 'command' previewList.trigger 'core:move-down' expect(previewList.find('li.operation:eq(1)')).toHaveClass 'selected' expect(commandPanel.miniEditor.getText()).toBe 'command' + previewList.trigger 'core:move-up' + expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' + expect(commandPanel.miniEditor.getText()).toBe 'command' + + it "doesn't select collapsed operations", -> + rootView.attachToDom() + previewList.trigger 'command-panel:collapse-result' + expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected' + previewList.trigger 'core:move-down' + expect(previewList.find('li.path:eq(1)')).toHaveClass 'selected' + previewList.trigger 'core:move-up' + expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected' describe "when move-to-top and move-to-bottom are triggered on the preview list", -> - it "selects the first/last operation", -> + it "selects the first path or last operation", -> rootView.attachToDom() expect(previewList.getOperations().length).toBeGreaterThan 0 expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' @@ -425,8 +437,8 @@ describe "CommandPanel", -> expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations()) previewList.trigger 'core:move-to-top' - expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected' - expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0] + expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected' + expect(previewList.getSelectedOperation()).toBeUndefined() describe "when core:confirm is triggered on the preview list", -> it "opens the operation's buffer, selects and scrolls to the search result, and refocuses the preview list", -> @@ -453,6 +465,15 @@ describe "CommandPanel", -> expect(executeHandler).not.toHaveBeenCalled() + it "toggles the expansion state when a path is selected", -> + rootView.attachToDom() + previewList.trigger 'core:move-to-top' + expect(previewList.find('li.path:first')).toHaveClass 'selected' + expect(previewList.find('li.path:first')).not.toHaveClass 'is-collapsed' + previewList.trigger 'core:confirm' + expect(previewList.find('li.path:first')).toHaveClass 'selected' + expect(previewList.find('li.path:first')).toHaveClass 'is-collapsed' + describe "when an operation in the preview list is clicked", -> it "opens the operation's buffer, selects the search result, and refocuses the preview list", -> spyOn(previewList, 'focus') @@ -465,3 +486,24 @@ describe "CommandPanel", -> expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath()) expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange() expect(previewList.focus).toHaveBeenCalled() + + describe "when a path in the preview list is clicked", -> + it "shows and hides the matches for that path", -> + rootView.attachToDom() + expect(previewList.find('li.path:first-child ul.matches')).toBeVisible() + previewList.find('li.path:first-child .path-details').mousedown() + expect(previewList.find('li.path:first-child ul.matches')).toBeHidden() + + previewList.find('li.path:first-child .path-details').mousedown() + expect(previewList.find('li.path:first-child ul.matches')).toBeVisible() + + describe "when command-panel:collapse-result and command-panel:expand-result are triggered", -> + it "collapses and selects the path, and then expands the selected path", -> + rootView.attachToDom() + expect(previewList.find('li.path:first-child ul.matches')).toBeVisible() + previewList.trigger 'command-panel:collapse-result' + expect(previewList.find('li.path:first-child ul.matches')).toBeHidden() + expect(previewList.find('li.path:first-child')).toHaveClass 'selected' + previewList.trigger 'command-panel:expand-result' + expect(previewList.find('li.path:first-child ul.matches')).toBeVisible() + expect(previewList.find('li.path:first-child')).toHaveClass 'selected' diff --git a/src/packages/gists/spec/gists-spec.coffee b/src/packages/gists/spec/gists-spec.coffee index ac6011168..55e107f88 100644 --- a/src/packages/gists/spec/gists-spec.coffee +++ b/src/packages/gists/spec/gists-spec.coffee @@ -19,15 +19,10 @@ describe "Gists package", -> [request, originalFxOffValue] = [] beforeEach -> - originalFxOffValue = $.fx.off - $.fx.off = true editor.trigger 'gist:create' expect($.ajax).toHaveBeenCalled() request = $.ajax.argsForCall[0][0] - afterEach -> - $.fx.off = originalFxOffValue - it "creates an Ajax request to api.github.com with the entire buffer contents as the Gist's content", -> expect(request.url).toBe 'https://api.github.com/gists' expect(request.type).toBe 'POST' @@ -46,7 +41,7 @@ describe "Gists package", -> expect(rootView.find('.notification')).toExist() expect(rootView.find('.notification .title').text()).toBe 'Gist 1 created' advanceClock(2000) - expect(rootView.find('.gist-notification')).not.toExist() + expect(rootView.find('.notification')).not.toExist() describe "when the editor has a selection", -> beforeEach -> diff --git a/static/atom.css b/static/atom.css index 382352314..02bd9be48 100644 --- a/static/atom.css +++ b/static/atom.css @@ -60,4 +60,16 @@ html, body { src: url("octicons-regular-webfont.woff") format("woff"); font-weight: normal; font-style: normal; +} + +.is-loading { + background-image: url(images/spinner.svg); + background-repeat: no-repeat; + width: 14px; + height: 14px; + opacity: 0.5; + background-size: contain; + position: relative; + display: inline-block; + padding-left: 19px; } \ No newline at end of file diff --git a/static/command-panel.css b/static/command-panel.css index 3fa292585..313f137f4 100644 --- a/static/command-panel.css +++ b/static/command-panel.css @@ -1,30 +1,77 @@ .command-panel { - padding: 5px; position: relative; + padding: 0; +} + +.command-panel .is-loading { + display: block; + margin: 0 auto 10px auto; + width: 100px; + background-color: #111; + background-size: auto; + background-position: 5px 5px; + padding: 5px 5px 10px 30px; + border-radius: 3px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-top: 1px solid rgba(0, 0, 0, 1); + border-left: 1px solid rgba(0, 0, 0, 1); } .command-panel .preview-list { max-height: 300px; overflow: auto; - margin: 10px 0 10px 10px; + margin: 0 0 10px 0; position: relative; cursor: default; } -.command-panel .preview-count { +.command-panel .header:after { + content: "."; + display: block; + visibility: hidden; + clear: both; + height: 0; +} + +.command-panel .expand-collapse { + float: right; +} + +.command-panel .expand-collapse li { + display: inline-block; + padding: 5px; + cursor: pointer; font-size: 11px; - text-align: right; - position: absolute; - right: 15px; - top: 24px; - z-index: 9999; +} + +.command-panel .preview-count, +.command-panel .expand-collapse { + -webkit-user-select: none; } .command-panel .preview-list .path { padding-left: 5px; + position: relative; + -webkit-user-select: none; } -.command-panel .preview-list .path:before { +.command-panel .preview-list .path-details:before { + font-family: 'Octicons Regular'; + font-size: 12px; + width: 12px; + height: 12px; + margin-right: 5px; + -webkit-font-smoothing: antialiased; + content: "\f05b"; + position: relative; + top: 0; +} + +.command-panel .preview-list .is-collapsed .path-details:before { + content: "\f05a"; +} + +.command-panel .preview-list .path-name:before { font-family: 'Octicons Regular'; font-size: 16px; width: 16px; @@ -36,13 +83,14 @@ top: 1px; } -.command-panel .preview-list .path.readme:before { +.command-panel .preview-list .path.readme .path-name:before { content: "\f007"; } .command-panel .preview-list .operation { padding-top: 2px; padding-bottom: 2px; + padding-left: 10px; } .command-panel .preview-list .line-number { @@ -65,20 +113,8 @@ padding: 1px; } -.command-panel .prompt-and-editor .prompt:before { - color: #969696; - content: '\f078'; - font-family: 'Octicons Regular'; - position: relative; - top: 0; - left: -5px; - -webkit-font-smoothing: antialiased; -} - .command-panel .prompt-and-editor .editor { position: relative; - left: -4px; - margin-right: -4px; } .command-panel .prompt-and-editor { diff --git a/static/images/spinner.svg b/static/images/spinner.svg new file mode 100644 index 000000000..90d8297c5 --- /dev/null +++ b/static/images/spinner.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/atom-dark-ui/command-panel.css b/themes/atom-dark-ui/command-panel.css index f2c6648ba..0014608b7 100644 --- a/themes/atom-dark-ui/command-panel.css +++ b/themes/atom-dark-ui/command-panel.css @@ -6,39 +6,89 @@ padding: 10px; } +.command-panel .header { + background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05)); + border: 1px solid rgba(0, 0, 0, 0.5); + padding: 5px; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.05), + inset 0 -1px 0 rgba(255, 255, 255, 0.02); + margin-bottom: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + .command-panel .preview-list { background-color: #19191b; - color: #C5C8C6; - border: 1px solid rgba(0, 0, 0, 0.5); + color: #6d736f; + border: 1px solid rgba(0, 0, 0, 0.2); border-bottom: 1px solid rgba(255, 255, 255, 0.05); border-right: 1px solid rgba(255, 255, 255, 0.05); } .command-panel .preview-count { + display: inline-block; + margin-top: 5px; color: #969696; - background: #161719; - padding: 5px; + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.05); +} + +.command-panel .expand-collapse { + color: #969696; +} + +.command-panel .expand-collapse li { + background: -webkit-linear-gradient(#19191a, #1a1b1c); + margin-left: 5px; + padding: 5px 10px; border-radius: 3px; + box-shadow: + inset -1px -1px 0 rgba(255, 255, 255, 0.1), + inset 1px 1px rgba(0, 0, 0, 0.1); } -.command-panel .preview-list li.selected, .command-panel .preview-list li.operation:hover { - background-color: rgba(255, 255, 255, .13); -} - -.command-panel .preview-list:focus li.selected { - background-color: rgba(255, 255, 255, .2); -} - -.command-panel .preview-list .path { +.command-panel .expand-collapse li:hover { color: #fff; } +.command-panel .preview-list .path.selected .path-details, +.command-panel .preview-list li.operation.selected { + background-color: rgba(255, 255, 255, 0.05); +} + +.command-panel .preview-list:focus .path.selected .path-details, +.command-panel .preview-list:focus li.operation.selected { + background-color: rgba(255, 255, 255, 0.05); +} + +.command-panel .preview-list .path { + color: #bbb; + border-top: 1px solid rgba(255, 255, 255, 0.02); +} + +.command-panel .preview-list .path:hover .path-name { + color: #fff; +} + +.command-panel .preview-list .path:before { + color: #555; +} + +.command-panel .preview-list .path:hover:before { + color: #fff; +} + +.command-panel .preview-list .path:first-child { + border-top: none; +} + .command-panel .preview-list .line-number { - color: rgba(255, 255, 255, .3); + color: rgba(255, 255, 255, 0.3); + font-family: monospace; } .command-panel .preview-list .path-match-number { - color: rgba(255, 255, 255, .3); + color: rgba(255, 255, 255, 0.3); } .command-panel .preview-list .preview { @@ -46,6 +96,18 @@ } .command-panel .preview-list .preview .match { - background-color: rgba(255, 255, 255, .2); - color: yellow; + background-color: rgba(255, 255, 255, 0.1); + color: #cca300; +} + +.command-panel .preview-list li.operation { + color: #777; +} + +.command-panel .preview-list li.operation:hover, +.command-panel li.operation.selected .preview { + color: #fff; +} + { + color: #fff; } diff --git a/themes/atom-light-ui/command-panel.css b/themes/atom-light-ui/command-panel.css index 34ced33e7..aac964ac4 100644 --- a/themes/atom-light-ui/command-panel.css +++ b/themes/atom-light-ui/command-panel.css @@ -2,12 +2,26 @@ background-color: #f4f4f4; border-top: 1px solid #979797; color: #ededed; + padding: 10px; +} + +.command-panel .header { + padding: 5px; + background-image: -webkit-linear-gradient(#e7e7e7, #cfcfcf); + border: 1px solid rgba(0, 0, 0, 0.2); + padding: 5px; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + +.command-panel .expand-collapse { + color: #333; } .command-panel .preview-list { background-color: #e7e7e7; color: #222; - border: 1px solid #989898; + border: 1px solid #ccc; } .command-panel .preview-count { @@ -19,11 +33,24 @@ } .command-panel .preview-list .path { - color: #3D5075; + color: #999; + border-top: 1px solid #ddd; +} + +.command-panel .preview-list .path-name { + color: #555; +} + +.command-panel .preview-list .path:before { + color: #555; +} + +.command-panel .preview-list .path:hover:before { + color: #000; } .command-panel .preview-list .line-number { - color: #3D5075; + color: #999; } .command-panel .preview-list .path-match-number { @@ -31,5 +58,10 @@ } .command-panel .preview-list .preview .match { - background-color: #c8d4d7; -} \ No newline at end of file + background-color: #bbb; + color: #333; +} + +.command-panel .preview-list li.operation { + color: #777; +}