From 92569b1f0d2a1e4a5b131ce560766b023a71ccb1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 1 Mar 2017 00:53:11 +0100 Subject: [PATCH] Improved dropdowns --- .../components/components/dropdown_menu.jsx | 40 ++++++++++++++---- .../components/status_action_bar.jsx | 16 ++++---- .../account/components/action_bar.jsx | 20 ++++----- .../features/status/components/action_bar.jsx | 9 ++-- .../javascripts/components/locales/en.jsx | 8 ++-- app/assets/stylesheets/components.scss | 41 +++++++++++++------ 6 files changed, 90 insertions(+), 44 deletions(-) diff --git a/app/assets/javascripts/components/components/dropdown_menu.jsx b/app/assets/javascripts/components/components/dropdown_menu.jsx index 0a8492b562..2b42eaa601 100644 --- a/app/assets/javascripts/components/components/dropdown_menu.jsx +++ b/app/assets/javascripts/components/components/dropdown_menu.jsx @@ -10,12 +10,44 @@ const DropdownMenu = React.createClass({ direction: React.PropTypes.string }, + getDefaultProps () { + return { + direction: 'left' + }; + }, + mixins: [PureRenderMixin], setRef (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
  • ; + } + + const { text, action, href = '#' } = item; + + return ( +
  • + + {text} + +
  • + ); + }, + render () { const { icon, items, size, direction } = this.props; const directionClass = (direction === "left") ? "dropdown__left" : "dropdown__right"; @@ -28,13 +60,7 @@ const DropdownMenu = React.createClass({ diff --git a/app/assets/javascripts/components/components/status_action_bar.jsx b/app/assets/javascripts/components/components/status_action_bar.jsx index 35c458b5ee..469506f2fe 100644 --- a/app/assets/javascripts/components/components/status_action_bar.jsx +++ b/app/assets/javascripts/components/components/status_action_bar.jsx @@ -6,13 +6,13 @@ import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, - mention: { id: 'status.mention', defaultMessage: 'Mention' }, - block: { id: 'account.block', defaultMessage: 'Block' }, + mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, reply: { id: 'status.reply', defaultMessage: 'Reply' }, reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, - open: { id: 'status.open', defaultMessage: 'Expand' }, - report: { id: 'status.report', defaultMessage: 'Report' } + open: { id: 'status.open', defaultMessage: 'Expand this status' }, + report: { id: 'status.report', defaultMessage: 'Report @{name}' } }); const StatusActionBar = React.createClass({ @@ -74,13 +74,15 @@ const StatusActionBar = React.createClass({ let menu = []; menu.push({ text: intl.formatMessage(messages.open), action: this.handleOpen }); + menu.push(null); if (status.getIn(['account', 'id']) === me) { menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); } else { - menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick }); - menu.push({ text: intl.formatMessage(messages.block), action: this.handleBlockClick }); - menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport }); + menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); + menu.push(null); + 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 ( diff --git a/app/assets/javascripts/components/features/account/components/action_bar.jsx b/app/assets/javascripts/components/features/account/components/action_bar.jsx index a2ab8172b6..48925817c9 100644 --- a/app/assets/javascripts/components/features/account/components/action_bar.jsx +++ b/app/assets/javascripts/components/features/account/components/action_bar.jsx @@ -5,14 +5,13 @@ import { Link } from 'react-router'; import { defineMessages, injectIntl, FormattedMessage, FormattedNumber } from 'react-intl'; 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' }, - unblock: { id: 'account.unblock', defaultMessage: 'Unblock' }, + unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, 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' }, - block: { id: 'account.block', defaultMessage: 'Block' }, - report: { id: 'account.report', defaultMessage: 'Report' } + report: { id: 'account.report', defaultMessage: 'Report @{name}' } }); const outerDropdownStyle = { @@ -45,20 +44,21 @@ const ActionBar = React.createClass({ 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) { menu.push({ text: intl.formatMessage(messages.edit_profile), href: '/settings/profile' }); } 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'])) { - 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 { - 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) { - 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 ( diff --git a/app/assets/javascripts/components/features/status/components/action_bar.jsx b/app/assets/javascripts/components/features/status/components/action_bar.jsx index cc4d5cca42..2acf942743 100644 --- a/app/assets/javascripts/components/features/status/components/action_bar.jsx +++ b/app/assets/javascripts/components/features/status/components/action_bar.jsx @@ -6,11 +6,11 @@ import { defineMessages, injectIntl } from 'react-intl'; const messages = defineMessages({ 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' }, reblog: { id: 'status.reblog', defaultMessage: 'Reblog' }, favourite: { id: 'status.favourite', defaultMessage: 'Favourite' }, - report: { id: 'status.report', defaultMessage: 'Report' } + report: { id: 'status.report', defaultMessage: 'Report @{name}' } }); const ActionBar = React.createClass({ @@ -66,8 +66,9 @@ const ActionBar = React.createClass({ if (me === status.getIn(['account', 'id'])) { menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick }); } else { - menu.push({ text: intl.formatMessage(messages.mention), action: this.handleMentionClick }); - menu.push({ text: intl.formatMessage(messages.report), action: this.handleReport }); + menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); + menu.push(null); + menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); } return ( diff --git a/app/assets/javascripts/components/locales/en.jsx b/app/assets/javascripts/components/locales/en.jsx index f1d6a6dbcc..e2aa4247ee 100644 --- a/app/assets/javascripts/components/locales/en.jsx +++ b/app/assets/javascripts/components/locales/en.jsx @@ -2,7 +2,7 @@ const en = { "column_back_button.label": "Back", "lightbox.close": "Close", "loading_indicator.label": "Loading...", - "status.mention": "Mention", + "status.mention": "Mention @{name}", "status.delete": "Delete", "status.reply": "Reply", "status.reblog": "Boost", @@ -11,11 +11,11 @@ const en = { "status.sensitive_warning": "Sensitive content", "status.sensitive_toggle": "Click to view", "video_player.toggle_sound": "Toggle sound", - "account.mention": "Mention", + "account.mention": "Mention @{name}", "account.edit_profile": "Edit profile", - "account.unblock": "Unblock", + "account.unblock": "Unblock @{name}", "account.unfollow": "Unfollow", - "account.block": "Block", + "account.block": "Block @{name}", "account.follow": "Follow", "account.posts": "Posts", "account.follows": "Follows", diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 3b7c6ddf4e..bb3001a15b 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -59,6 +59,10 @@ &.active { color: $color4; } + + &:focus { + outline: none; + } } .invisible { @@ -516,6 +520,12 @@ a.status__content__spoiler-link { position: absolute; } +.dropdown__sep { + border-bottom: 1px solid darken($color2, 8%); + margin: 5px 7px 6px; + padding-top: 1px; +} + .dropdown--active .dropdown__content { display: block; z-index: 9999; @@ -539,17 +549,33 @@ a.status__content__spoiler-link { padding: 4px 0; border-radius: 4px; 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 { font-size: 13px; + line-height: 18px; display: block; - padding: 6px 16px; - width: 100px; + padding: 4px 14px; + box-sizing: border-box; + width: 140px; text-decoration: none; background: $color2; color: $color1; + overflow: hidden; + text-overflow: ellipsis; + + &:focus { + outline: none; + } &:hover { 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 { color: $color3; background: transparent;