Improved dropdowns
This commit is contained in:
		
							parent
							
								
									f8fa1d604c
								
							
						
					
					
						commit
						58ddd1d3a2
					
				
					 6 changed files with 90 additions and 44 deletions
				
			
		|  | @ -10,12 +10,44 @@ const DropdownMenu = React.createClass({ | ||||||
|     direction: React.PropTypes.string |     direction: React.PropTypes.string | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  |   getDefaultProps () { | ||||||
|  |     return { | ||||||
|  |       direction: 'left' | ||||||
|  |     }; | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|   mixins: [PureRenderMixin], |   mixins: [PureRenderMixin], | ||||||
| 
 | 
 | ||||||
|   setRef (c) { |   setRef (c) { | ||||||
|     this.dropdown = c; |     this.dropdown = c; | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  |   handleClick (i, e) { | ||||||
|  |     const { action } = this.props.items[i]; | ||||||
|  | 
 | ||||||
|  |     if (typeof action === 'function') { | ||||||
|  |       e.preventDefault(); | ||||||
|  |       action(); | ||||||
|  |       this.dropdown.hide(); | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|  |   renderItem (item, i) { | ||||||
|  |     if (item === null) { | ||||||
|  |       return <li key={i} className='dropdown__sep' />; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const { text, action, href = '#' } = item; | ||||||
|  | 
 | ||||||
|  |     return ( | ||||||
|  |       <li key={i}> | ||||||
|  |         <a href={href} target='_blank' rel='noopener' onClick={this.handleClick.bind(this, i)}> | ||||||
|  |           {text} | ||||||
|  |         </a> | ||||||
|  |       </li> | ||||||
|  |     ); | ||||||
|  |   }, | ||||||
|  | 
 | ||||||
|   render () { |   render () { | ||||||
|     const { icon, items, size, direction } = this.props; |     const { icon, items, size, direction } = this.props; | ||||||
|     const directionClass = (direction === "left") ? "dropdown__left" : "dropdown__right"; |     const directionClass = (direction === "left") ? "dropdown__left" : "dropdown__right"; | ||||||
|  | @ -28,13 +60,7 @@ const DropdownMenu = React.createClass({ | ||||||
| 
 | 
 | ||||||
|         <DropdownContent className={directionClass} style={{ lineHeight: '18px', textAlign: 'left' }}> |         <DropdownContent className={directionClass} style={{ lineHeight: '18px', textAlign: 'left' }}> | ||||||
|           <ul> |           <ul> | ||||||
|             {items.map(({ text, action, href = '#' }, i) => <li key={i}><a href={href} target='_blank' rel='noopener' onClick={e => { |             {items.map(this.renderItem)} | ||||||
|               if (typeof action === 'function') { |  | ||||||
|                 e.preventDefault(); |  | ||||||
|                 action(); |  | ||||||
|                 this.dropdown.hide(); |  | ||||||
|               } |  | ||||||
|             }}>{text}</a></li>)} |  | ||||||
|           </ul> |           </ul> | ||||||
|         </DropdownContent> |         </DropdownContent> | ||||||
|       </Dropdown> |       </Dropdown> | ||||||
|  |  | ||||||
|  | @ -6,13 +6,13 @@ import { defineMessages, injectIntl } from 'react-intl'; | ||||||
| 
 | 
 | ||||||
| const messages = defineMessages({ | const messages = defineMessages({ | ||||||
|   delete: { id: 'status.delete', defaultMessage: 'Delete' }, |   delete: { id: 'status.delete', defaultMessage: 'Delete' }, | ||||||
|   mention: { id: 'status.mention', defaultMessage: 'Mention' }, |   mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, | ||||||
|   block: { id: 'account.block', defaultMessage: 'Block' }, |   block: { id: 'account.block', defaultMessage: 'Block @{name}' }, | ||||||
|   reply: { id: 'status.reply', defaultMessage: 'Reply' }, |   reply: { id: 'status.reply', defaultMessage: 'Reply' }, | ||||||
|   reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, |   reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, | ||||||
|   favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, |   favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, | ||||||
|   open: { id: 'status.open', defaultMessage: 'Expand' }, |   open: { id: 'status.open', defaultMessage: 'Expand this status' }, | ||||||
|   report: { id: 'status.report', defaultMessage: 'Report' } |   report: { id: 'status.report', defaultMessage: 'Report @{name}' } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const StatusActionBar = React.createClass({ | const StatusActionBar = React.createClass({ | ||||||
|  | @ -74,13 +74,15 @@ const StatusActionBar = React.createClass({ | ||||||
|     let menu = []; |     let menu = []; | ||||||
| 
 | 
 | ||||||
|     menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen }); |     menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen }); | ||||||
|  |     menu.push(null); | ||||||
| 
 | 
 | ||||||
|     if (status.getIn(['account', 'id']) === me) { |     if (status.getIn(['account', 'id']) === me) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); |       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); | ||||||
|     } else { |     } else { | ||||||
|       menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick }); |       menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); | ||||||
|       menu.push({ text: intl.formatMessage(messages.block), action: this.handleBlockClick }); |       menu.push(null); | ||||||
|       menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport }); |       menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); | ||||||
|  |       menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|  |  | ||||||
|  | @ -5,14 +5,13 @@ import { Link } from 'react-router'; | ||||||
| import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; | import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; | ||||||
| 
 | 
 | ||||||
| const messages = defineMessages({ | const messages = defineMessages({ | ||||||
|   mention: { id: 'account.mention', defaultMessage: 'Mention' }, |   mention: { id: 'account.mention', defaultMessage: 'Mention @{name}' }, | ||||||
|   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, |   edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, | ||||||
|   unblock: { id: 'account.unblock', defaultMessage: 'Unblock' }, |   unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, | ||||||
|   unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, |   unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, | ||||||
|   block: { id: 'account.block', defaultMessage: 'Block' }, |   block: { id: 'account.block', defaultMessage: 'Block @{name}' }, | ||||||
|   follow: { id: 'account.follow', defaultMessage: 'Follow' }, |   follow: { id: 'account.follow', defaultMessage: 'Follow' }, | ||||||
|   block: { id: 'account.block', defaultMessage: 'Block' }, |   report: { id: 'account.report', defaultMessage: 'Report @{name}' } | ||||||
|   report: { id: 'account.report', defaultMessage: 'Report' } |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const outerDropdownStyle = { | const outerDropdownStyle = { | ||||||
|  | @ -45,20 +44,21 @@ const ActionBar = React.createClass({ | ||||||
| 
 | 
 | ||||||
|     let menu = []; |     let menu = []; | ||||||
| 
 | 
 | ||||||
|     menu.push({ text: intl.formatMessage(messages.mention), action: this.props.onMention }); |     menu.push({ text: intl.formatMessage(messages.mention, { name: account.get('username') }), action: this.props.onMention }); | ||||||
|  |     menu.push(null); | ||||||
| 
 | 
 | ||||||
|     if (account.get('id') === me) { |     if (account.get('id') === me) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); |       menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); | ||||||
|     } else if (account.getIn(['relationship', 'blocking'])) { |     } else if (account.getIn(['relationship', 'blocking'])) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.unblock), action: this.props.onBlock }); |       menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock }); | ||||||
|     } else if (account.getIn(['relationship', 'following'])) { |     } else if (account.getIn(['relationship', 'following'])) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock }); |       menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); | ||||||
|     } else { |     } else { | ||||||
|       menu.push({ text: intl.formatMessage(messages.block), action: this.props.onBlock }); |       menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (account.get('id') !== me) { |     if (account.get('id') !== me) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.report), action: this.props.onReport }); |       menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|  |  | ||||||
|  | @ -6,11 +6,11 @@ import { defineMessages, injectIntl } from 'react-intl'; | ||||||
| 
 | 
 | ||||||
| const messages = defineMessages({ | const messages = defineMessages({ | ||||||
|   delete: { id: 'status.delete', defaultMessage: 'Delete' }, |   delete: { id: 'status.delete', defaultMessage: 'Delete' }, | ||||||
|   mention: { id: 'status.mention', defaultMessage: 'Mention' }, |   mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, | ||||||
|   reply: { id: 'status.reply', defaultMessage: 'Reply' }, |   reply: { id: 'status.reply', defaultMessage: 'Reply' }, | ||||||
|   reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, |   reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, | ||||||
|   favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, |   favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, | ||||||
|   report: { id: 'status.report', defaultMessage: 'Report' } |   report: { id: 'status.report', defaultMessage: 'Report @{name}' } | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const ActionBar = React.createClass({ | const ActionBar = React.createClass({ | ||||||
|  | @ -66,8 +66,9 @@ const ActionBar = React.createClass({ | ||||||
|     if (me === status.getIn(['account', 'id'])) { |     if (me === status.getIn(['account', 'id'])) { | ||||||
|       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); |       menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); | ||||||
|     } else { |     } else { | ||||||
|       menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick }); |       menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); | ||||||
|       menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport }); |       menu.push(null); | ||||||
|  |       menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ const en = { | ||||||
|   "column_back_button.label": "Back", |   "column_back_button.label": "Back", | ||||||
|   "lightbox.close": "Close", |   "lightbox.close": "Close", | ||||||
|   "loading_indicator.label": "Loading...", |   "loading_indicator.label": "Loading...", | ||||||
|   "status.mention": "Mention", |   "status.mention": "Mention @{name}", | ||||||
|   "status.delete": "Delete", |   "status.delete": "Delete", | ||||||
|   "status.reply": "Reply", |   "status.reply": "Reply", | ||||||
|   "status.reblog": "Boost", |   "status.reblog": "Boost", | ||||||
|  | @ -11,11 +11,11 @@ const en = { | ||||||
|   "status.sensitive_warning": "Sensitive content", |   "status.sensitive_warning": "Sensitive content", | ||||||
|   "status.sensitive_toggle": "Click to view", |   "status.sensitive_toggle": "Click to view", | ||||||
|   "video_player.toggle_sound": "Toggle sound", |   "video_player.toggle_sound": "Toggle sound", | ||||||
|   "account.mention": "Mention", |   "account.mention": "Mention @{name}", | ||||||
|   "account.edit_profile": "Edit profile", |   "account.edit_profile": "Edit profile", | ||||||
|   "account.unblock": "Unblock", |   "account.unblock": "Unblock @{name}", | ||||||
|   "account.unfollow": "Unfollow", |   "account.unfollow": "Unfollow", | ||||||
|   "account.block": "Block", |   "account.block": "Block @{name}", | ||||||
|   "account.follow": "Follow", |   "account.follow": "Follow", | ||||||
|   "account.posts": "Posts", |   "account.posts": "Posts", | ||||||
|   "account.follows": "Follows", |   "account.follows": "Follows", | ||||||
|  |  | ||||||
|  | @ -59,6 +59,10 @@ | ||||||
|   &.active { |   &.active { | ||||||
|     color: $color4; |     color: $color4; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   &:focus { | ||||||
|  |     outline: none; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .invisible { | .invisible { | ||||||
|  | @ -516,6 +520,12 @@ a.status__content__spoiler-link { | ||||||
|   position: absolute; |   position: absolute; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .dropdown__sep { | ||||||
|  |   border-bottom: 1px solid darken($color2, 8%); | ||||||
|  |   margin: 5px 7px 6px; | ||||||
|  |   padding-top: 1px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .dropdown--active .dropdown__content { | .dropdown--active .dropdown__content { | ||||||
|   display: block; |   display: block; | ||||||
|   z-index: 9999; |   z-index: 9999; | ||||||
|  | @ -539,17 +549,33 @@ a.status__content__spoiler-link { | ||||||
|     padding: 4px 0; |     padding: 4px 0; | ||||||
|     border-radius: 4px; |     border-radius: 4px; | ||||||
|     box-shadow: 0 0 15px rgba($color8, 0.4); |     box-shadow: 0 0 15px rgba($color8, 0.4); | ||||||
|     min-width: 100px; |     min-width: 140px; | ||||||
|  |     position: relative; | ||||||
|  |     left: -10px; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   &.dropdown__left { | ||||||
|  |     ul { | ||||||
|  |       left: -98px; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   a { |   a { | ||||||
|     font-size: 13px; |     font-size: 13px; | ||||||
|  |     line-height: 18px; | ||||||
|     display: block; |     display: block; | ||||||
|     padding: 6px 16px; |     padding: 4px 14px; | ||||||
|     width: 100px; |     box-sizing: border-box; | ||||||
|  |     width: 140px; | ||||||
|     text-decoration: none; |     text-decoration: none; | ||||||
|     background: $color2; |     background: $color2; | ||||||
|     color: $color1; |     color: $color1; | ||||||
|  |     overflow: hidden; | ||||||
|  |     text-overflow: ellipsis; | ||||||
|  | 
 | ||||||
|  |     &:focus { | ||||||
|  |       outline: none; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     &:hover { |     &:hover { | ||||||
|       background: $color4; |       background: $color4; | ||||||
|  | @ -983,15 +1009,6 @@ a.status__content__spoiler-link { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .dropdown__content.dropdown__left { |  | ||||||
|   transform: translateX(-108px); |  | ||||||
| 
 |  | ||||||
|   &::before { |  | ||||||
|     right: 8px !important; |  | ||||||
|     left: initial !important; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .setting-text { | .setting-text { | ||||||
|   color: $color3; |   color: $color3; | ||||||
|   background: transparent; |   background: transparent; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue