diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
index 0474dfb4e..d5bb58712 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.js
@@ -2,7 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
import IconButton from '../../../components/icon_button';
+import { Overlay } from 'react-overlays';
+import { Motion, spring } from 'react-motion';
import detectPassiveEvents from 'detect-passive-events';
+import classNames from 'classnames';
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
@@ -16,10 +19,77 @@ const messages = defineMessages({
change_privacy: { id: 'privacy.change', defaultMessage: 'Adjust status privacy' },
});
-const iconStyle = {
- height: null,
- lineHeight: '27px',
-};
+const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
+
+class PrivacyDropdownMenu extends React.PureComponent {
+
+ static propTypes = {
+ style: PropTypes.object,
+ items: PropTypes.array.isRequired,
+ value: PropTypes.string.isRequired,
+ onClose: PropTypes.func.isRequired,
+ onChange: PropTypes.func.isRequired,
+ };
+
+ handleDocumentClick = e => {
+ if (this.node && !this.node.contains(e.target)) {
+ this.props.onClose();
+ }
+ }
+
+ handleClick = e => {
+ if (e.key === 'Escape') {
+ this.props.onClose();
+ } else if (!e.key || e.key === 'Enter') {
+ const value = e.currentTarget.getAttribute('data-index');
+
+ e.preventDefault();
+
+ this.props.onClose();
+ this.props.onChange(value);
+ }
+ }
+
+ componentDidMount () {
+ document.addEventListener('click', this.handleDocumentClick, false);
+ document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
+ }
+
+ componentWillUnmount () {
+ document.removeEventListener('click', this.handleDocumentClick, false);
+ document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
+ }
+
+ setRef = c => {
+ this.node = c;
+ }
+
+ render () {
+ const { style, items, value } = this.props;
+
+ return (
+
+ {({ opacity, scaleX, scaleY }) => (
+
+ {items.map(item =>
+
+
+
+
+
+
+ {item.text}
+ {item.meta}
+
+
+ )}
+
+ )}
+
+ );
+ }
+
+}
@injectIntl
export default class PrivacyDropdown extends React.PureComponent {
@@ -55,26 +125,30 @@ export default class PrivacyDropdown extends React.PureComponent {
handleModalActionClick = (e) => {
e.preventDefault();
+
const { value } = this.options[e.currentTarget.getAttribute('data-index')];
+
this.props.onModalClose();
this.props.onChange(value);
}
- handleClick = (e) => {
- if (e.key === 'Escape') {
- this.setState({ open: false });
- } else if (!e.key || e.key === 'Enter') {
- const value = e.currentTarget.getAttribute('data-index');
- e.preventDefault();
- this.setState({ open: false });
- this.props.onChange(value);
+ handleKeyDown = e => {
+ switch(e.key) {
+ case 'Enter':
+ this.handleToggle();
+ break;
+ case 'Escape':
+ this.handleClose();
+ break;
}
}
- onGlobalClick = (e) => {
- if (e.target !== this.node && !this.node.contains(e.target) && this.state.open) {
- this.setState({ open: false });
- }
+ handleClose = () => {
+ this.setState({ open: false });
+ }
+
+ handleChange = value => {
+ this.props.onChange(value);
}
componentWillMount () {
@@ -88,20 +162,6 @@ export default class PrivacyDropdown extends React.PureComponent {
];
}
- componentDidMount () {
- window.addEventListener('click', this.onGlobalClick);
- window.addEventListener('touchstart', this.onGlobalClick, detectPassiveEvents.hasSupport ? { passive: true } : false);
- }
-
- componentWillUnmount () {
- window.removeEventListener('click', this.onGlobalClick);
- window.removeEventListener('touchstart', this.onGlobalClick, detectPassiveEvents.hasSupport ? { passive: true } : false);
- }
-
- setRef = (c) => {
- this.node = c;
- }
-
render () {
const { value, intl } = this.props;
const { open } = this.state;
@@ -109,19 +169,29 @@ export default class PrivacyDropdown extends React.PureComponent {
const valueOption = this.options.find(item => item.value === value);
return (
-
-
-
- {open && this.options.map(item =>
-
-
-
- {item.text}
- {item.meta}
-
-
- )}
+
);
}
diff --git a/app/javascript/mastodon/features/compose/components/warning.js b/app/javascript/mastodon/features/compose/components/warning.js
index 75f36b840..dc902f33b 100644
--- a/app/javascript/mastodon/features/compose/components/warning.js
+++ b/app/javascript/mastodon/features/compose/components/warning.js
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { Motion, spring } from 'react-motion';
export default class Warning extends React.PureComponent {
@@ -11,9 +12,13 @@ export default class Warning extends React.PureComponent {
const { message } = this.props;
return (
-
- {message}
-
+
+ {({ opacity, scaleX, scaleY }) => (
+
+ {message}
+
+ )}
+
);
}
diff --git a/app/javascript/styles/components.scss b/app/javascript/styles/components.scss
index 5ea0d134e..caa7c0787 100644
--- a/app/javascript/styles/components.scss
+++ b/app/javascript/styles/components.scss
@@ -1275,7 +1275,7 @@
background: $ui-secondary-color;
padding: 4px 0;
border-radius: 4px;
- box-shadow: 0 0 15px rgba($base-shadow-color, 0.4);
+ box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
ul {
list-style: none;
@@ -2805,19 +2805,12 @@ button.icon-button.active i.fa-retweet {
filter: none;
}
-.privacy-dropdown {
- position: relative;
-}
-
.privacy-dropdown__dropdown {
- display: none;
position: absolute;
- left: 0;
- top: 27px;
- width: 230px;
background: $simple-background-color;
- border-radius: 0 4px 4px;
- z-index: 2;
+ box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
+ border-radius: 4px;
+ margin-left: 40px;
overflow: hidden;
}
@@ -2869,6 +2862,18 @@ button.icon-button.active i.fa-retweet {
background: $simple-background-color;
border-radius: 4px 4px 0 0;
box-shadow: 0 -4px 4px rgba($base-shadow-color, 0.1);
+
+ .icon-button {
+ transition: none;
+ }
+
+ &.active {
+ background: $ui-highlight-color;
+
+ .icon-button {
+ color: $primary-text-color;
+ }
+ }
}
.privacy-dropdown__dropdown {
diff --git a/app/javascript/styles/rtl.scss b/app/javascript/styles/rtl.scss
index 0fdeccd9c..67bfa8a38 100644
--- a/app/javascript/styles/rtl.scss
+++ b/app/javascript/styles/rtl.scss
@@ -128,22 +128,8 @@ body.rtl {
}
.privacy-dropdown__dropdown {
- left: auto;
- right: 0;
- }
-
- .dropdown--active .dropdown__content {
- text-align: right;
- }
-
- .dropdown--active .dropdown__content::before {
- left: auto;
- right: 8px;
- }
-
- .dropdown--active .dropdown__content > ul {
- left: auto;
- right: -10px;
+ margin-left: 0;
+ margin-right: 40px;
}
.privacy-dropdown__option__icon {