feat(composer): floating toolbar now fades in

Summary: tooltip fades in now

Test Plan: edgehill --test

Reviewers: bengotow

Reviewed By: bengotow

Differential Revision: https://review.inboxapp.com/D1317
This commit is contained in:
Evan Morikawa 2015-03-19 17:16:38 -07:00
parent 891f86ebce
commit 1d99a18bf6
4 changed files with 73 additions and 23 deletions

View file

@ -29,10 +29,12 @@ ContenteditableComponent = React.createClass
componentDidMount: ->
@_setupSelectionListeners()
@_setupLinkHoverListeners()
@_setupGlobalMouseListener()
componentWillUnmount: ->
@_teardownSelectionListeners()
@_teardownLinkHoverListeners()
@_teardownGlobalMouseListener()
componentWillReceiveProps: (nextProps) ->
if nextProps.initialSelectionSnapshot?
@ -69,8 +71,6 @@ ContenteditableComponent = React.createClass
onBlur={@_onBlur}
onPaste={@_onPaste}
onInput={@_onInput}
onMouseUp={@_onMouseUp}
onMouseDown={@_onMouseDown}
dangerouslySetInnerHTML={@_dangerouslySetInnerHTML()}></div>
<a className={@_quotedTextClasses()} onClick={@_onToggleQuotedText}></a>
</div>
@ -79,7 +79,7 @@ ContenteditableComponent = React.createClass
@_editableNode().focus() if @isMounted()
_onInput: (event) ->
@_ignoreSelectionRestoration = false
@_dragging = false
@_editableNode().normalize()
@_setNewSelectionState()
html = @_unapplyHTMLDisplayFilters(@_editableNode().innerHTML)
@ -212,17 +212,46 @@ ContenteditableComponent = React.createClass
@_previousSelection = @_selection
@_selection = selection
# When we're dragging we don't want to the restoring the cursor as we're
# dragging. Doing so caused selecting backwards to break because the
# Selection API does not yet expose the selection "direction". When we
# would go to reset the cursor selection, it would reset to the wrong
# state.
# We use global listeners to determine whether or not dragging is
# happening. This is because dragging may stop outside the scope of
# this element. Note that the `dragstart` and `dragend` events don't
# detect text selection. They are for drag & drop.
_setupGlobalMouseListener: ->
@__onMouseDown = _.bind(@_onMouseDown, @)
@__onMouseMove = _.bind(@_onMouseMove, @)
@__onMouseUp = _.bind(@_onMouseUp, @)
window.addEventListener("mousedown", @__onMouseDown)
window.addEventListener("mouseup", @__onMouseUp)
_teardownGlobalMouseListener: ->
window.removeEventListener("mousedown", @__onMouseDown)
window.removeEventListener("mouseup", @__onMouseUp)
_onMouseDown: (event) ->
@_ignoreSelectionRestoration = true
return event
@_mouseDownEvent = event
@_mouseHasMoved = false
window.addEventListener("mousemove", @__onMouseMove)
_onMouseMove: (event) ->
if not @_mouseHasMoved
@_onDragStart(@_mouseDownEvent)
@_mouseHasMoved = true
_onMouseUp: (event) ->
@_ignoreSelectionRestoration = false
return event
window.removeEventListener("mousemove", @__onMouseMove)
if @_mouseHasMoved
@_mouseHasMoved = false
@_onDragEnd(event)
_onDragStart: (event) ->
return unless @isMounted()
editable = @refs.contenteditable.getDOMNode()
if editable is event.target or editable.contains(event.target)
@_dragging = true
_onDragEnd: (event) ->
return unless @isMounted()
if @_dragging
@_dragging = false
@_refreshToolbarState()
# We manually restore the selection on every render and when we need to
# move the selection around manually.
@ -234,7 +263,7 @@ ContenteditableComponent = React.createClass
# selection, we'll collapse the range into a single caret
# position
_restoreSelection: ({force, collapse}={}) ->
return if @_ignoreSelectionRestoration
return if @_dragging
return if not @_selection?
return if document.activeElement isnt @_editableNode() and not force
return if not @_selection.startNode? or not @_selection.endNode?
@ -354,6 +383,7 @@ ContenteditableComponent = React.createClass
# 2. When you've arrow-keyed the cursor into a link
# 3. When you have selected a range of text.
_refreshToolbarState: ->
return if @_dragging
if @_linkHoveringOver
url = @_linkHoveringOver.getAttribute('href')
rect = @_linkHoveringOver.getBoundingClientRect()

View file

@ -1,5 +1,5 @@
_ = require 'underscore-plus'
React = require 'react'
React = require 'react/addons'
{CompositeDisposable} = require 'event-kit'
{RetinaImg} = require 'ui-components'
@ -32,11 +32,25 @@ FloatingToolbar = React.createClass
render: ->
<div ref="floatingToolbar"
className="floating-toolbar toolbar #{@props.pos}" style={@_toolbarStyles()}>
className={@_toolbarClasses()} style={@_toolbarStyles()}>
<div className="toolbar-pointer" style={@_toolbarPointerStyles()}></div>
{@_toolbarType()}
</div>
_toolbarClasses: ->
classes = {}
classes[@props.pos] = true
React.addons.classSet _.extend classes,
"floating-toolbar": true
"toolbar": true
"toolbar-visible": @props.visible
_toolbarStyles: ->
styles =
left: @_toolbarLeft()
top: @props.top
return styles
_toolbarType: ->
if @state.mode is "buttons" then @_renderButtons()
else if @state.mode is "edit-link" then @_renderLink()
@ -118,13 +132,6 @@ FloatingToolbar = React.createClass
document.execCommand(cmd, false, null)
true
_toolbarStyles: ->
styles =
left: @_toolbarLeft()
top: @props.top
display: if @props.visible then "block" else "none"
return styles
_toolbarLeft: ->
CONTENT_PADDING = @props.contentPadding ? 15
max = @props.editAreaWidth - @_halfWidth()*2 - CONTENT_PADDING

View file

@ -322,6 +322,19 @@ body.is-blurred .composer-inner-wrap .tokenizing-field .token {
border-radius: @border-radius-base;
color: @text-color;
transition-duration: .15s;
// transition-delay: .1s;
transition-property: opacity, margin;
opacity: 0;
visibility: hidden;
margin-top: 3px;
&.toolbar-visible {
opacity: 1;
visibility: visible;
margin-top: 0px;
}
.toolbar-pointer {
position: absolute;
width: 22.5px;

View file

@ -43,7 +43,7 @@ ThreadList = React.createClass
selectedId={@state.selectedId}
onSelect={ (item) -> Actions.selectThreadId(item.id) } />
</div>
_computeColumns: ->
labelComponents = (thread) =>
for label in @state.threadLabelComponents