fix(popover): don't let popover overflow

Summary:
The popover class now will adjust itself until it fits within the window
frame. You don't see the intermediate state in the double render.

Test Plan: edgehill --test

Reviewers: bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D1795
This commit is contained in:
Evan Morikawa 2015-07-23 19:42:16 -07:00
parent 60ccd86de1
commit 9eb36f5813
5 changed files with 43 additions and 18 deletions

View file

@ -28,12 +28,12 @@
}
.message-toolbar-arrow.down {
order:101;
order:201;
margin-right: 0;
padding-top:6px;
}
.message-toolbar-arrow.up {
order:102;
order:202;
padding-top:6px;
// <1 because of hit region padding on the button
margin-right: @spacing-standard * 0.75;

View file

@ -153,10 +153,10 @@ class Tooltip extends React.Component
return left
_windowWidth: =>
document.getElementsByTagName('body')[0].getBoundingClientRect().width
document.body.offsetWidth
_windowHeight: =>
document.getElementsByTagName('body')[0].getBoundingClientRect().height
document.body.offsetHeight
_hideTooltip: =>
@_lastTarget = null

View file

@ -213,10 +213,6 @@
'tab': 'native!'
'shift-tab': 'native!'
# For Popover Component
'body .popover-container, body .popover-container input':
'escape': 'popover:close'
# Tokenizing Text fields
# The default state. There's no input in the text field and there are no

View file

@ -68,20 +68,21 @@ class Popover extends React.Component
constructor: (@props) ->
@state =
showing: false
offset: 0
dimensions: {}
componentDidMount: =>
@subscriptions = new CompositeDisposable()
@subscriptions.add atom.commands.add '.popover-container', {
'popover:close': => @close()
}
window.addEventListener("resize", @_resetPositionState)
@_resetPositionState()
componentWillUnmount: =>
@subscriptions?.dispose()
window.removeEventListener("resize", @_resetPositionState)
componentDidUpdate: ->
if @_focusOnOpen
@_focusImportantElement()
@_focusOnOpen = false
@_resetPositionState()
open: =>
@_focusOnOpen = true
@ -94,6 +95,26 @@ class Popover extends React.Component
showing: false
@props.onClosed?()
# We need to make sure that we're not rendered off the edge of the
# browser window.
_resetPositionState: ->
return unless @state.showing
rect = React.findDOMNode(@refs.popover).getBoundingClientRect()
dimensions =
left: rect.left
right: rect.right
docWidth: document.body.clientWidth
return if _.isEqual dimensions, @state.dimensions
padding = 11.25
origRight = dimensions.right - @state.offset
origLeft = dimensions.left - @state.offset
offset = Math.min((dimensions.docWidth - padding - origRight), 0) - Math.min(origLeft - padding, 0)
@setState {offset, dimensions}
_focusImportantElement: =>
# Automatically focus the element inside us with the lowest tab index
node = React.findDOMNode(@refs.popover)
@ -113,10 +134,12 @@ class Popover extends React.Component
wrappedButtonComponent = <div onClick={@_onClick}>{@props.buttonComponent}</div>
popoverComponent = []
if @state.showing
popoverStyle =
'position': 'absolute'
'left': '50%'
'left': "calc(50% + #{@state.offset})"
'width': '250px'
'zIndex': 40
pointerStyle =
'position': 'absolute'
@ -147,7 +170,7 @@ class Popover extends React.Component
popoverStyle = _.extend popoverStyle,
'transform': 'translate(0, 2px)'
'top': '100%'
'left': 0
'left': 0 + @state.offset
pointerStyle = _.extend pointerStyle,
'display': 'none'
@ -156,11 +179,18 @@ class Popover extends React.Component
<div className="popover-pointer" style={pointerStyle}></div>
</div>
<div className={"popover-container "+@props.className} onBlur={@_onBlur} ref="container" style={(@props.style ? {})}>
<div className={"popover-container "+@props.className}
onBlur={@_onBlur}
onKeyDown={@_onKeyDown}
style={(@props.style ? {})} ref="popoverContainer">
{wrappedButtonComponent}
{popoverComponent}
</div>
_onKeyDown: (event) =>
if event.key is "Escape"
@close()
_onClick: =>
if not @state.showing
@open()
@ -169,7 +199,7 @@ class Popover extends React.Component
_onBlur: (event) =>
target = event.nativeEvent.relatedTarget
if target? and React.findDOMNode(@refs.container).contains(target)
if target? and React.findDOMNode(@refs.popoverContainer).contains(target)
return
@setState
showing:false

View file

@ -8,7 +8,6 @@
.popover {
display: flex;
flex-direction: column;
width: 250px;
max-height:400px;
background-color: @background-color;
border-radius: @border-radius-base;