diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx
index 97b54e50d3..4901ee2182 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.jsx
+++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx
@@ -23,7 +23,7 @@ import { useColumnsContext } from '../util/columns_context';
import BundleColumnError from './bundle_column_error';
import { ColumnLoading } from './column_loading';
-import ComposePanel from './compose_panel';
+import { ComposePanel } from './compose_panel';
import DrawerLoading from './drawer_loading';
import NavigationPanel from './navigation_panel';
diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.jsx b/app/javascript/mastodon/features/ui/components/compose_panel.jsx
deleted file mode 100644
index e622c8859a..0000000000
--- a/app/javascript/mastodon/features/ui/components/compose_panel.jsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import PropTypes from 'prop-types';
-import { PureComponent } from 'react';
-
-import { connect } from 'react-redux';
-
-import { changeComposing, mountCompose, unmountCompose } from 'mastodon/actions/compose';
-import ServerBanner from 'mastodon/components/server_banner';
-import { Search } from 'mastodon/features/compose/components/search';
-import ComposeFormContainer from 'mastodon/features/compose/containers/compose_form_container';
-import { LinkFooter } from 'mastodon/features/ui/components/link_footer';
-import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
-
-class ComposePanel extends PureComponent {
- static propTypes = {
- identity: identityContextPropShape,
- dispatch: PropTypes.func.isRequired,
- };
-
- onFocus = () => {
- const { dispatch } = this.props;
- dispatch(changeComposing(true));
- };
-
- onBlur = () => {
- const { dispatch } = this.props;
- dispatch(changeComposing(false));
- };
-
- componentDidMount () {
- const { dispatch } = this.props;
- dispatch(mountCompose());
- }
-
- componentWillUnmount () {
- const { dispatch } = this.props;
- dispatch(unmountCompose());
- }
-
- render() {
- const { signedIn } = this.props.identity;
-
- return (
-
-
-
- {!signedIn && (
- <>
-
-
- >
- )}
-
- {signedIn && (
-
- )}
-
-
-
- );
- }
-
-}
-
-export default connect()(withIdentity(ComposePanel));
diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.tsx b/app/javascript/mastodon/features/ui/components/compose_panel.tsx
new file mode 100644
index 0000000000..aa15520309
--- /dev/null
+++ b/app/javascript/mastodon/features/ui/components/compose_panel.tsx
@@ -0,0 +1,56 @@
+import { useCallback, useEffect } from 'react';
+
+import { useLayout } from '@/mastodon/hooks/useLayout';
+import { useAppDispatch, useAppSelector } from '@/mastodon/store';
+import {
+ changeComposing,
+ mountCompose,
+ unmountCompose,
+} from 'mastodon/actions/compose';
+import ServerBanner from 'mastodon/components/server_banner';
+import { Search } from 'mastodon/features/compose/components/search';
+import ComposeFormContainer from 'mastodon/features/compose/containers/compose_form_container';
+import { LinkFooter } from 'mastodon/features/ui/components/link_footer';
+import { useIdentity } from 'mastodon/identity_context';
+
+export const ComposePanel: React.FC = () => {
+ const dispatch = useAppDispatch();
+ const handleFocus = useCallback(() => {
+ dispatch(changeComposing(true));
+ }, [dispatch]);
+ const { signedIn } = useIdentity();
+ const hideComposer = useAppSelector((state) => {
+ const mounted = state.compose.get('mounted');
+ if (typeof mounted === 'number') {
+ return mounted > 1;
+ }
+ return false;
+ });
+
+ useEffect(() => {
+ dispatch(mountCompose());
+ return () => {
+ dispatch(unmountCompose());
+ };
+ }, [dispatch]);
+
+ const { singleColumn } = useLayout();
+
+ return (
+
+
+
+ {!signedIn && (
+ <>
+
+
+ >
+ )}
+
+ {signedIn && !hideComposer &&
}
+ {signedIn && hideComposer &&
}
+
+
+
+ );
+};
diff --git a/app/javascript/mastodon/hooks/useLayout.ts b/app/javascript/mastodon/hooks/useLayout.ts
new file mode 100644
index 0000000000..fc1cf136bf
--- /dev/null
+++ b/app/javascript/mastodon/hooks/useLayout.ts
@@ -0,0 +1,13 @@
+import type { LayoutType } from '../is_mobile';
+import { useAppSelector } from '../store';
+
+export const useLayout = () => {
+ const layout = useAppSelector(
+ (state) => state.meta.get('layout') as LayoutType,
+ );
+
+ return {
+ singleColumn: layout === 'single-column' || layout === 'mobile',
+ layout,
+ };
+};