forked from cybrespace/mastodon
Improved dropdowns
This commit is contained in:
parent
955e9088d7
commit
92569b1f0d
|
@ -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 New Issue