diff --git a/app/javascript/flavours/glitch/features/compose/components/content_type_button.jsx b/app/javascript/flavours/glitch/features/compose/components/content_type_button.jsx
index 9ac382091e..c1d6860bde 100644
--- a/app/javascript/flavours/glitch/features/compose/components/content_type_button.jsx
+++ b/app/javascript/flavours/glitch/features/compose/components/content_type_button.jsx
@@ -1,17 +1,14 @@
-import { useCallback, useState, useRef } from 'react';
+import { useCallback } from 'react';
import { useIntl, defineMessages } from 'react-intl';
-import Overlay from 'react-overlays/Overlay';
-
import CodeIcon from '@/material-icons/400-24px/code.svg?react';
import DescriptionIcon from '@/material-icons/400-24px/description.svg?react';
import MarkdownIcon from '@/material-icons/400-24px/markdown.svg?react';
import { changeComposeContentType } from 'flavours/glitch/actions/compose';
-import { IconButton } from 'flavours/glitch/components/icon_button';
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
-import DropdownMenu from './dropdown_menu';
+import { DropdownIconButton } from './dropdown_icon_button';
const messages = defineMessages({
change_content_type: { id: 'compose.content-type.change', defaultMessage: 'Change advanced formatting options' },
@@ -30,38 +27,10 @@ export const ContentTypeButton = () => {
const contentType = useAppSelector((state) => state.getIn(['compose', 'content_type']));
const dispatch = useAppDispatch();
- const containerRef = useRef(null);
-
- const [activeElement, setActiveElement] = useState(null);
- const [open, setOpen] = useState(false);
- const [placement, setPlacement] = useState('bottom');
-
- const handleToggle = useCallback(() => {
- if (open && activeElement) {
- activeElement.focus({ preventScroll: true });
- setActiveElement(null);
- }
-
- setOpen(!open);
- }, [open, setOpen, activeElement, setActiveElement]);
-
- const handleClose = useCallback(() => {
- if (open && activeElement) {
- activeElement.focus({ preventScroll: true });
- setActiveElement(null);
- }
-
- setOpen(false);
- }, [open, setOpen, activeElement, setActiveElement]);
-
const handleChange = useCallback((value) => {
dispatch(changeComposeContentType(value));
}, [dispatch]);
- const handleOverlayEnter = useCallback((state) => {
- setPlacement(state.placement);
- }, [setPlacement]);
-
if (!showButton) {
return null;
}
@@ -85,31 +54,13 @@ export const ContentTypeButton = () => {
}[contentType];
return (
-
-
-
-
- {({ props, placement }) => (
-
- )}
-
-
+
);
};
diff --git a/app/javascript/flavours/glitch/features/compose/components/dropdown_icon_button.jsx b/app/javascript/flavours/glitch/features/compose/components/dropdown_icon_button.jsx
new file mode 100644
index 0000000000..58a9e633fb
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/compose/components/dropdown_icon_button.jsx
@@ -0,0 +1,76 @@
+import PropTypes from 'prop-types';
+import { useCallback, useState, useRef } from 'react';
+
+import Overlay from 'react-overlays/Overlay';
+
+import { IconButton } from 'flavours/glitch/components/icon_button';
+
+import DropdownMenu from './dropdown_menu';
+
+export const DropdownIconButton = ({ value, icon, onChange, iconComponent, title, options }) => {
+ const containerRef = useRef(null);
+
+ const [activeElement, setActiveElement] = useState(null);
+ const [open, setOpen] = useState(false);
+ const [placement, setPlacement] = useState('bottom');
+
+ const handleToggle = useCallback(() => {
+ if (open && activeElement) {
+ activeElement.focus({ preventScroll: true });
+ setActiveElement(null);
+ }
+
+ setOpen(!open);
+ }, [open, setOpen, activeElement, setActiveElement]);
+
+ const handleClose = useCallback(() => {
+ if (open && activeElement) {
+ activeElement.focus({ preventScroll: true });
+ setActiveElement(null);
+ }
+
+ setOpen(false);
+ }, [open, setOpen, activeElement, setActiveElement]);
+
+ const handleOverlayEnter = useCallback((state) => {
+ setPlacement(state.placement);
+ }, [setPlacement]);
+
+ return (
+
+
+
+
+ {({ props, placement }) => (
+
+ )}
+
+
+ );
+};
+
+DropdownIconButton.propTypes = {
+ value: PropTypes.string.isRequired,
+ icon: PropTypes.string,
+ onChange: PropTypes.func.isRequired,
+ iconComponent: PropTypes.func.isRequired,
+ options: PropTypes.array.isRequired,
+ title: PropTypes.string.isRequired,
+};
diff --git a/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx b/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx
index a7ef0aa028..a1bb53f692 100644
--- a/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx
+++ b/app/javascript/flavours/glitch/features/compose/components/federation_button.jsx
@@ -1,16 +1,13 @@
-import { useCallback, useState, useRef } from 'react';
+import { useCallback } from 'react';
import { useIntl, defineMessages } from 'react-intl';
-import Overlay from 'react-overlays/Overlay';
-
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
import ShareOffIcon from '@/material-icons/400-24px/share_off.svg?react';
import { changeComposeAdvancedOption } from 'flavours/glitch/actions/compose';
-import { IconButton } from 'flavours/glitch/components/icon_button';
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
-import DropdownMenu from './dropdown_menu';
+import { DropdownIconButton } from './dropdown_icon_button';
const messages = defineMessages({
change_federation_settings: { id: 'compose.change_federation', defaultMessage: 'Change federation settings' },
@@ -26,69 +23,23 @@ export const FederationButton = () => {
const do_not_federate = useAppSelector((state) => state.getIn(['compose', 'advanced_options', 'do_not_federate']));
const dispatch = useAppDispatch();
- const containerRef = useRef(null);
-
- const [activeElement, setActiveElement] = useState(null);
- const [open, setOpen] = useState(false);
- const [placement, setPlacement] = useState('bottom');
-
- const handleToggle = useCallback(() => {
- if (open && activeElement) {
- activeElement.focus({ preventScroll: true });
- setActiveElement(null);
- }
-
- setOpen(!open);
- }, [open, setOpen, activeElement, setActiveElement]);
-
- const handleClose = useCallback(() => {
- if (open && activeElement) {
- activeElement.focus({ preventScroll: true });
- setActiveElement(null);
- }
-
- setOpen(false);
- }, [open, setOpen, activeElement, setActiveElement]);
-
const handleChange = useCallback((value) => {
dispatch(changeComposeAdvancedOption('do_not_federate', value === 'local-only'));
}, [dispatch]);
- const handleOverlayEnter = useCallback((state) => {
- setPlacement(state.placement);
- }, [setPlacement]);
-
const options = [
{ icon: 'link', iconComponent: ShareIcon, value: 'federated', text: intl.formatMessage(messages.federated_label), meta: intl.formatMessage(messages.federated_meta) },
{ icon: 'link-slash', iconComponent: ShareOffIcon, value: 'local-only', text: intl.formatMessage(messages.local_only_label), meta: intl.formatMessage(messages.local_only_meta) },
];
return (
-
-
-
-
- {({ props, placement }) => (
-
- )}
-
-
+
);
};