fix(dropdown): Open up or down depending on position

This commit is contained in:
Ben Gotow 2016-01-29 15:51:00 -08:00
parent 2027901deb
commit eec7c829ce
3 changed files with 53 additions and 22 deletions

View file

@ -87,7 +87,7 @@ class SendActionButton extends React.Component
_renderSendDropdown: -> _renderSendDropdown: ->
actionConfigs = @_orderedActionConfigs() actionConfigs = @_orderedActionConfigs()
<ButtonDropdown <ButtonDropdown
className={"btn-send dropdown-btn-emphasis dropdown-btn-text"} className={"btn-send btn-emphasis btn-text"}
style={order: -100} style={order: -100}
primaryItem={@_sendContent(actionConfigs[0].iconUrl)} primaryItem={@_sendContent(actionConfigs[0].iconUrl)}
primaryTitle={actionConfigs[0].title} primaryTitle={actionConfigs[0].title}

View file

@ -1,5 +1,6 @@
RetinaImg = require './retina-img' RetinaImg = require './retina-img'
{Utils} = require 'nylas-exports' {Utils} = require 'nylas-exports'
classnames = require 'classnames'
React = require 'react' React = require 'react'
class ButtonDropdown extends React.Component class ButtonDropdown extends React.Component
@ -16,15 +17,17 @@ class ButtonDropdown extends React.Component
style: {} style: {}
constructor: (@props) -> constructor: (@props) ->
@state = showing: false @state = open: false
render: => render: =>
classnames = "button-dropdown #{@props.className ? ''}" classes = classnames
classnames += " open" if @state.showing 'button-dropdown': true
classnames += " bordered" if @props.bordered isnt false 'open open-up': @state.open is 'up'
'open open-down': @state.open is 'down'
'bordered': @props.bordered isnt false
if @props.primaryClick if @props.primaryClick
<div ref="button" onBlur={@_onBlur} tabIndex={999} className={classnames} style={@props.style}> <div ref="button" onBlur={@_onBlur} tabIndex={999} className={"#{classes} #{@props.className ? ''}"} style={@props.style}>
<div className="primary-item" <div className="primary-item"
title={@props.primaryTitle ? ""} title={@props.primaryTitle ? ""}
onClick={@props.primaryClick}> onClick={@props.primaryClick}>
@ -33,34 +36,42 @@ class ButtonDropdown extends React.Component
<div className="secondary-picker" onClick={@toggleDropdown}> <div className="secondary-picker" onClick={@toggleDropdown}>
<RetinaImg name={"icon-thread-disclosure.png"} mode={RetinaImg.Mode.ContentIsMask}/> <RetinaImg name={"icon-thread-disclosure.png"} mode={RetinaImg.Mode.ContentIsMask}/>
</div> </div>
<div className="secondary-items" onMouseDown={@_onMenuClick}> <div ref="secondaryItems" className="secondary-items" onMouseDown={@_onMenuClick}>
{@props.menu} {@props.menu}
</div> </div>
</div> </div>
else else
<div ref="button" onBlur={@_onBlur} tabIndex={999} className={classnames} style={@props.style}> <div ref="button" onBlur={@_onBlur} tabIndex={999} className={"#{classes} #{@props.className ? ''}"} style={@props.style}>
<div className="only-item" <div className="only-item"
title={@props.primaryTitle ? ""} title={@props.primaryTitle ? ""}
onClick={@toggleDropdown}> onClick={@toggleDropdown}>
{@props.primaryItem} {@props.primaryItem}
<RetinaImg name={"icon-thread-disclosure.png"} style={marginLeft:12} mode={RetinaImg.Mode.ContentIsMask}/> <RetinaImg name={"icon-thread-disclosure.png"} style={marginLeft:12} mode={RetinaImg.Mode.ContentIsMask}/>
</div> </div>
<div className="secondary-items left" onMouseDown={@_onMenuClick}> <div ref="secondaryItems" className="secondary-items left" onMouseDown={@_onMenuClick}>
{@props.menu} {@props.menu}
</div> </div>
</div> </div>
toggleDropdown: => toggleDropdown: =>
@setState(showing: !@state.showing) if @state.open isnt false
@setState(open: false)
else
buttonBottom = React.findDOMNode(@).getBoundingClientRect().bottom
openHeight = React.findDOMNode(@refs.secondaryItems).getBoundingClientRect().height
if buttonBottom + openHeight > window.innerHeight
@setState(open: 'up')
else
@setState(open: 'down')
_onMenuClick: (event) => _onMenuClick: (event) =>
if @props.closeOnMenuClick if @props.closeOnMenuClick
@setState showing: false @setState open: false
_onBlur: (event) => _onBlur: (event) =>
target = event.nativeEvent.relatedTarget target = event.nativeEvent.relatedTarget
if target? and React.findDOMNode(@refs.button).contains(target) if target? and React.findDOMNode(@refs.button).contains(target)
return return
@setState(showing: false) @setState(open: false)
module.exports = ButtonDropdown module.exports = ButtonDropdown

View file

@ -5,14 +5,33 @@
display: inline-block; display: inline-block;
&.open { &.open {
.secondary-items {
visibility: inherit;
}
}
&.open.open-up {
.secondary-items {
border-radius: 4px 4px 0 4px;
box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.20);
top: -100%;
transform:translate(0, -2px);
}
.secondary-picker {
border-top-right-radius: 0;
}
}
&.open.open-down {
.secondary-items {
border-radius: 4px 0 4px 4px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.20);
}
.secondary-picker { .secondary-picker {
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
.secondary-items {
display:block;
}
} }
&.bordered, &.bordered,
&:hover { &:hover {
.primary-item, .primary-item,
@ -25,15 +44,18 @@
} }
} }
&.dropdown-btn-emphasis { &.btn-emphasis {
.primary-item, .primary-item,
.secondary-picker, .secondary-picker,
.only-item { .only-item {
.btn.btn-emphasis; .btn.btn-emphasis;
} }
.primary-item {
border-right:0;
}
} }
&.dropdown-btn-text { &.btn-text {
.primary-item, .primary-item,
.secondary-picker, .secondary-picker,
.only-item { .only-item {
@ -97,15 +119,13 @@
white-space:nowrap; white-space:nowrap;
} }
border: 1px solid rgba(0, 0, 0, 0.15); border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 4px 0 4px 4px;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.20);
z-index: 2; z-index: 2;
background-color: @background-primary; background-color: @background-primary;
line-height: 14px; line-height: 14px;
position: absolute; position: absolute;
right: -1px; // -1, because of the border above right: -1px; // -1, because of the border above
white-space:nowrap; white-space:nowrap;
display:none; visibility:hidden;
.menu { .menu {
.footer-container, .footer-container,
@ -168,7 +188,7 @@ body.platform-win32 {
.secondary-items { .secondary-items {
border-radius: 0; border-radius: 0;
} }
&.dropdown-btn-emphasis { &.btn-emphasis {
.primary-item, .primary-item,
.secondary-picker, .secondary-picker,
.only-item { .only-item {
@ -184,7 +204,7 @@ body.platform-win32 {
} }
} }
} }
&.dropdown-btn-text { &.btn-text {
.primary-item, .primary-item,
.secondary-picker, .secondary-picker,
.only-item { .only-item {