diff --git a/src/components/common/messaging/Message.tsx b/src/components/common/messaging/Message.tsx
index 03c13596de618cc0c024b0480bd5b1d0b2ecbf13..dfe9793d2edcfc6b938c4f906defea91a5fda8ee 100644
--- a/src/components/common/messaging/Message.tsx
+++ b/src/components/common/messaging/Message.tsx
@@ -1,5 +1,5 @@
-import UserIcon from "../UserIcon";
-import { Username } from "../UserShort";
+import UserIcon from "../user/UserIcon";
+import { Username } from "../user/UserShort";
 import Markdown from "../../markdown/Markdown";
 import { Children } from "../../../types/Preact";
 import { attachContextMenu } from "preact-context-menu";
diff --git a/src/components/common/messaging/MessageBox.tsx b/src/components/common/messaging/MessageBox.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ae980526104ef78ea76e02bb91a7fb4be5625896
--- /dev/null
+++ b/src/components/common/messaging/MessageBox.tsx
@@ -0,0 +1,89 @@
+import { useContext } from "preact/hooks";
+import { Channel } from "revolt.js";
+import { ulid } from "ulid";
+import { AppContext } from "../../../context/revoltjs/RevoltClient";
+import { takeError } from "../../../context/revoltjs/util";
+import { defer } from "../../../lib/defer";
+import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
+import { SingletonMessageRenderer, SMOOTH_SCROLL_ON_RECEIVE } from "../../../lib/renderer/Singleton";
+import { connectState } from "../../../redux/connector";
+import { WithDispatcher } from "../../../redux/reducers";
+import TextArea from "../../ui/TextArea";
+
+type Props = WithDispatcher & {
+    channel: Channel;
+    draft?: string;
+};
+
+function MessageBox({ channel, draft, dispatcher }: Props) {
+    const client = useContext(AppContext);
+
+    function setMessage(content?: string) {
+        if (content) {
+            dispatcher({
+                type: "SET_DRAFT",
+                channel: channel._id,
+                content
+            });
+        } else {
+            dispatcher({
+                type: "CLEAR_DRAFT",
+                channel: channel._id
+            });
+        }
+    }
+
+    async function send() {
+        const nonce = ulid();
+
+        const content = draft?.trim() ?? '';
+        if (content.length === 0) return;
+
+        setMessage();
+        dispatcher({
+            type: "QUEUE_ADD",
+            nonce,
+            channel: channel._id,
+            message: {
+                _id: nonce,
+                channel: channel._id,
+                author: client.user!._id,
+                content
+            }
+        });
+
+        defer(() => SingletonMessageRenderer.jumpToBottom(channel._id, SMOOTH_SCROLL_ON_RECEIVE));
+        // Sounds.playOutbound();
+
+        try {
+            await client.channels.sendMessage(channel._id, {
+                content,
+                nonce
+            });
+        } catch (error) {
+            dispatcher({
+                type: "QUEUE_FAIL",
+                error: takeError(error),
+                nonce
+            });
+        }
+    }
+
+    return (
+        <TextArea
+            value={draft}
+            onKeyDown={e => {
+                if (!e.shiftKey && e.key === "Enter" && !isTouchscreenDevice) {
+                    e.preventDefault();
+                    return send();
+                }
+            }}
+            onChange={e => setMessage(e.currentTarget.value)} />
+    )
+}
+
+export default connectState<Omit<Props, "dispatcher" | "draft">>(MessageBox, (state, { channel }) => {
+    return {
+        draft: state.drafts[channel._id]
+    }
+}, true)
diff --git a/src/components/common/messaging/SystemMessage.tsx b/src/components/common/messaging/SystemMessage.tsx
index c867f915601fb21424cb697618537c7851906ab5..26de5f59e12341a824dbde2b0680114c90515d35 100644
--- a/src/components/common/messaging/SystemMessage.tsx
+++ b/src/components/common/messaging/SystemMessage.tsx
@@ -4,9 +4,9 @@ import { attachContextMenu } from "preact-context-menu";
 import { MessageObject } from "../../../context/revoltjs/util";
 import { useForceUpdate, useUser } from "../../../context/revoltjs/hooks";
 import { TextReact } from "../../../lib/i18n";
-import UserIcon from "../UserIcon";
-import Username from "../UserShort";
-import UserShort from "../UserShort";
+import UserIcon from "../user/UserIcon";
+import Username from "../user/UserShort";
+import UserShort from "../user/UserShort";
 import MessageBase, { MessageDetail, MessageInfo } from "./MessageBase";
 import styled from "styled-components";
 
diff --git a/src/components/common/UserCheckbox.tsx b/src/components/common/user/UserCheckbox.tsx
similarity index 85%
rename from src/components/common/UserCheckbox.tsx
rename to src/components/common/user/UserCheckbox.tsx
index 35577ebc1a3bb6cacaeccf9db1ba2fc2d0ccbc1a..05cb69f71eab4b8cdcbafef8fd2ec952e48b3a77 100644
--- a/src/components/common/UserCheckbox.tsx
+++ b/src/components/common/user/UserCheckbox.tsx
@@ -1,6 +1,6 @@
 import { User } from "revolt.js";
 import UserIcon from "./UserIcon";
-import Checkbox, { CheckboxProps } from "../ui/Checkbox";
+import Checkbox, { CheckboxProps } from "../../ui/Checkbox";
 
 type UserProps = Omit<CheckboxProps, "children"> & { user: User };
 
diff --git a/src/components/common/UserHeader.tsx b/src/components/common/user/UserHeader.tsx
similarity index 88%
rename from src/components/common/UserHeader.tsx
rename to src/components/common/user/UserHeader.tsx
index 6a8265e34524a6b9bd35d143caabe87b9d7202a6..848e8ce84ef9abba30d70de7561693d0be33761b 100644
--- a/src/components/common/UserHeader.tsx
+++ b/src/components/common/user/UserHeader.tsx
@@ -1,17 +1,17 @@
-import Tooltip from "./Tooltip";
+import Tooltip from "../Tooltip";
 import { User } from "revolt.js";
-import Header from "../ui/Header";
 import UserIcon from "./UserIcon";
 import { Text } from "preact-i18n";
+import Header from "../../ui/Header";
 import UserStatus from './UserStatus';
 import styled from "styled-components";
 import { Localizer } from 'preact-i18n';
 import { Link } from "react-router-dom";
-import IconButton from "../ui/IconButton";
+import IconButton from "../../ui/IconButton";
 import { Settings } from "@styled-icons/feather";
 import { openContextMenu } from "preact-context-menu";
-import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
-import { useIntermediate } from "../../context/intermediate/Intermediate";
+import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
+import { useIntermediate } from "../../../context/intermediate/Intermediate";
 
 const HeaderBase = styled.div`
     gap: 0;
diff --git a/src/components/common/UserIcon.tsx b/src/components/common/user/UserIcon.tsx
similarity index 92%
rename from src/components/common/UserIcon.tsx
rename to src/components/common/user/UserIcon.tsx
index 5e9243fdd66ec1acab4949cd67fa3ab5a5e58a03..65418b7196bef80f45198dc09f7947d15ccaf807 100644
--- a/src/components/common/UserIcon.tsx
+++ b/src/components/common/user/UserIcon.tsx
@@ -2,10 +2,10 @@ import { User } from "revolt.js";
 import { useContext } from "preact/hooks";
 import { MicOff } from "@styled-icons/feather";
 import styled, { css } from "styled-components";
-import { ThemeContext } from "../../context/Theme";
 import { Users } from "revolt.js/dist/api/objects";
-import IconBase, { IconBaseProps } from "./IconBase";
-import { AppContext } from "../../context/revoltjs/RevoltClient";
+import { ThemeContext } from "../../../context/Theme";
+import IconBase, { IconBaseProps } from "../IconBase";
+import { AppContext } from "../../../context/revoltjs/RevoltClient";
 
 type VoiceStatus = "muted";
 interface Props extends IconBaseProps<User> {
@@ -47,7 +47,7 @@ const VoiceIndicator = styled.div<{ status: VoiceStatus }>`
     ` }
 `;
 
-import fallback from './assets/user.png';
+import fallback from '../assets/user.png';
 
 export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>) {
     const client = useContext(AppContext);
diff --git a/src/components/common/UserShort.tsx b/src/components/common/user/UserShort.tsx
similarity index 100%
rename from src/components/common/UserShort.tsx
rename to src/components/common/user/UserShort.tsx
diff --git a/src/components/common/UserStatus.tsx b/src/components/common/user/UserStatus.tsx
similarity index 100%
rename from src/components/common/UserStatus.tsx
rename to src/components/common/user/UserStatus.tsx
diff --git a/src/components/navigation/items/ButtonItem.tsx b/src/components/navigation/items/ButtonItem.tsx
index bcbd59aadd0281a813257fb084cdcc243e4f39e8..4f5064e8e3ff71cfa27a4c7fee50c57c10e65740 100644
--- a/src/components/navigation/items/ButtonItem.tsx
+++ b/src/components/navigation/items/ButtonItem.tsx
@@ -2,12 +2,12 @@ import classNames from 'classnames';
 import styles from "./Item.module.scss";
 import Tooltip from '../../common/Tooltip';
 import IconButton from '../../ui/IconButton';
-import UserIcon from '../../common/UserIcon';
 import { Localizer, Text } from "preact-i18n";
 import { X, Zap } from "@styled-icons/feather";
-import UserStatus from '../../common/UserStatus';
 import { Children } from "../../../types/Preact";
+import UserIcon from '../../common/user/UserIcon';
 import ChannelIcon from '../../common/ChannelIcon';
+import UserStatus from '../../common/user/UserStatus';
 import { attachContextMenu } from 'preact-context-menu';
 import { Channels, Users } from "revolt.js/dist/api/objects";
 import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
diff --git a/src/components/navigation/left/HomeSidebar.tsx b/src/components/navigation/left/HomeSidebar.tsx
index a3082f354d517245725f3ff00e264bf3b6f7adc8..9c6cf7a4c59df032e99990477bb3770335af3789 100644
--- a/src/components/navigation/left/HomeSidebar.tsx
+++ b/src/components/navigation/left/HomeSidebar.tsx
@@ -2,23 +2,23 @@ import { Localizer, Text } from "preact-i18n";
 import { useContext } from "preact/hooks";
 import { Home, Users, Tool, Save } from "@styled-icons/feather";
 
-import { Link, Redirect, useLocation, useParams } from "react-router-dom";
+import styled from "styled-components";
+import Category from '../../ui/Category';
+import PaintCounter from "../../../lib/PaintCounter";
+import UserHeader from "../../common/user/UserHeader";
+import { Channels } from "revolt.js/dist/api/objects";
+import { connectState } from "../../../redux/connector";
+import ConnectionStatus from '../items/ConnectionStatus';
 import { WithDispatcher } from "../../../redux/reducers";
 import { Unreads } from "../../../redux/reducers/unreads";
-import { connectState } from "../../../redux/connector";
-import { AppContext } from "../../../context/revoltjs/RevoltClient";
-import { useChannels, useDMs, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
-import { Users as UsersNS } from 'revolt.js/dist/api/objects';
 import { mapChannelWithUnread, useUnreads } from "./common";
-import { Channels } from "revolt.js/dist/api/objects";
-import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
-import ConnectionStatus from '../items/ConnectionStatus';
+import { Users as UsersNS } from 'revolt.js/dist/api/objects';
 import ButtonItem, { ChannelButton } from '../items/ButtonItem';
-import styled from "styled-components";
-import UserHeader from "../../common/UserHeader";
-import Category from '../../ui/Category';
-import PaintCounter from "../../../lib/PaintCounter";
+import { AppContext } from "../../../context/revoltjs/RevoltClient";
+import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
+import { Link, Redirect, useLocation, useParams } from "react-router-dom";
 import { useIntermediate } from "../../../context/intermediate/Intermediate";
+import { useDMs, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
 
 type Props = WithDispatcher & {
     unreads: Unreads;
@@ -126,7 +126,11 @@ function HomeSidebar(props: Props) {
                     let user;
                     if (x.channel_type === 'DirectMessage') {
                         let recipient = client.channels.getRecipient(x._id);
-                        user = users.find(x => x!._id === recipient);
+                        user = users.find(x => x?._id === recipient);
+                        if (!user) {
+                            console.warn(`Skipped DM ${x._id} because user was missing.`);
+                            return null;
+                        }
                     }
                     
                     return (
diff --git a/src/components/ui/TextArea.tsx b/src/components/ui/TextArea.tsx
index d88dcb7b3ae2185087f6b86b6521a5b73eccbb4c..ed15695f320fc7366588fee3320928f5649da7fb 100644
--- a/src/components/ui/TextArea.tsx
+++ b/src/components/ui/TextArea.tsx
@@ -1,12 +1,37 @@
-// ! FIXME: temporarily here until re-written
-// ! DO NOT IMRPOVE, JUST RE-WRITE
+// import classNames from "classnames";
+// import { memo } from "preact/compat";
+// import styles from "./TextArea.module.scss";
+// import { useState, useEffect, useRef, useLayoutEffect } from "preact/hooks";
+import styled, { css } from "styled-components";
+
+interface Props {
+    code?: boolean;
+}
+
+export default styled.textarea<Props>`
+    width: 100%;
+    resize: none;
+    display: block;
+    border-radius: 4px;
+
+    color: var(--foreground);
+    border: 2px solid transparent;
+    background: var(--secondary-background);
+    transition: border-color .2s ease-in-out;
+
+    &:focus {
+        outline: none;
+        border: 2px solid var(--accent);
+    }
 
-import classNames from "classnames";
-import { memo } from "preact/compat";
-import styles from "./TextArea.module.scss";
-import { useState, useEffect, useRef, useLayoutEffect } from "preact/hooks";
+    ${ props => props.code ? css`
+        font-family: 'Fira Mono', 'Courier New', Courier, monospace;
+    ` : css`
+        font-family: 'Open Sans', sans-serif;
+    ` }
+`;
 
-export interface TextAreaProps {
+/*export interface TextAreaProps {
     id?: string;
     value: string;
     maxRows?: number;
@@ -30,7 +55,7 @@ export interface TextAreaProps {
 
 const lineHeight = 20;
 
-export const TextArea = memo((props: TextAreaProps) => {
+export const TextAreaB = memo((props: TextAreaProps) => {
     const padding = props.padding ? props.padding * 2 : 0;
 
     const [height, setHeightState] = useState(
@@ -143,4 +168,4 @@ export const TextArea = memo((props: TextAreaProps) => {
             </div>
         </div>
     );
-});
+});*/
diff --git a/src/context/intermediate/modals/Prompt.tsx b/src/context/intermediate/modals/Prompt.tsx
index 3a1dac547142e85598ddc51d80bec398311c0df0..1a48e624b427ef3b31dee431517826c4f45ba73b 100644
--- a/src/context/intermediate/modals/Prompt.tsx
+++ b/src/context/intermediate/modals/Prompt.tsx
@@ -4,12 +4,12 @@ import { Children } from "../../../types/Preact";
 import { useIntermediate } from "../Intermediate";
 import InputBox from "../../../components/ui/InputBox";
 import Overline from "../../../components/ui/Overline";
-import UserIcon from "../../../components/common/UserIcon";
+import { AppContext } from "../../revoltjs/RevoltClient";
+import { mapMessage, takeError } from "../../revoltjs/util";
 import Modal, { Action } from "../../../components/ui/Modal";
 import { Channels, Servers } from "revolt.js/dist/api/objects";
 import { useContext, useEffect, useState } from "preact/hooks";
-import { AppContext } from "../../revoltjs/RevoltClient";
-import { mapMessage, takeError } from "../../revoltjs/util";
+import UserIcon from "../../../components/common/user/UserIcon";
 import Message from "../../../components/common/messaging/Message";
 
 interface Props {
diff --git a/src/context/intermediate/popovers/UserPicker.tsx b/src/context/intermediate/popovers/UserPicker.tsx
index 9c2a8e609ad13a15e3684501b38d5ffb7f245dd5..b4ab76ca90139f9cdf3eb4ac4a0e42305cd86075 100644
--- a/src/context/intermediate/popovers/UserPicker.tsx
+++ b/src/context/intermediate/popovers/UserPicker.tsx
@@ -4,7 +4,7 @@ import styles from "./UserPicker.module.scss";
 import { useUsers } from "../../revoltjs/hooks";
 import Modal from "../../../components/ui/Modal";
 import { User, Users } from "revolt.js/dist/api/objects";
-import UserCheckbox from "../../../components/common/UserCheckbox";
+import UserCheckbox from "../../../components/common/user/UserCheckbox";
 
 interface Props {
     omit?: string[];
diff --git a/src/context/intermediate/popovers/UserProfile.tsx b/src/context/intermediate/popovers/UserProfile.tsx
index 0a11cfd8fd03af92fb1557d4bdca1074e3468299..2b37ee7c3aaa802075fab9021b979c2c8e0ac365 100644
--- a/src/context/intermediate/popovers/UserProfile.tsx
+++ b/src/context/intermediate/popovers/UserProfile.tsx
@@ -1,22 +1,22 @@
-import Modal from "../../../components/ui/Modal";
+import { decodeTime } from "ulid";
 import { Localizer, Text } from "preact-i18n";
 import styles from "./UserProfile.module.scss";
-import Preloader from "../../../components/ui/Preloader";
+import Modal from "../../../components/ui/Modal";
 import { Route } from "revolt.js/dist/api/routes";
 import { Users } from "revolt.js/dist/api/objects";
-import { IntermediateContext, useIntermediate } from "../Intermediate";
-import { Globe, Mail, Edit, UserPlus, Shield } from "@styled-icons/feather";
+import { useIntermediate } from "../Intermediate";
 import { Link, useHistory } from "react-router-dom";
-import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks";
-import { decodeTime } from "ulid";
 import { CashStack } from "@styled-icons/bootstrap";
-import { AppContext, ClientStatus, StatusContext } from "../../revoltjs/RevoltClient";
-import { useChannels, useForceUpdate, useUser, useUsers } from "../../revoltjs/hooks";
-import UserIcon from '../../../components/common/UserIcon';
-import UserStatus from '../../../components/common/UserStatus';
+import Preloader from "../../../components/ui/Preloader";
 import Tooltip from '../../../components/common/Tooltip';
-import ChannelIcon from '../../../components/common/ChannelIcon';
 import Markdown from '../../../components/markdown/Markdown';
+import UserIcon from '../../../components/common/user/UserIcon';
+import ChannelIcon from '../../../components/common/ChannelIcon';
+import UserStatus from '../../../components/common/user/UserStatus';
+import { Mail, Edit, UserPlus, Shield } from "@styled-icons/feather";
+import { useChannels, useForceUpdate, useUsers } from "../../revoltjs/hooks";
+import { useContext, useEffect, useLayoutEffect, useState } from "preact/hooks";
+import { AppContext, ClientStatus, StatusContext } from "../../revoltjs/RevoltClient";
 
 interface Props {
     user_id: string;
diff --git a/src/context/revoltjs/CheckAuth.tsx b/src/context/revoltjs/CheckAuth.tsx
index f084e933f6587f2cc8fc07f601ee9134ea7faba8..1951985efed70317a1f87f1d24a26a260954d90e 100644
--- a/src/context/revoltjs/CheckAuth.tsx
+++ b/src/context/revoltjs/CheckAuth.tsx
@@ -1,12 +1,12 @@
-import { ReactNode } from "react";
 import { useContext } from "preact/hooks";
 import { Redirect } from "react-router-dom";
+import { Children } from "../../types/Preact";
 
 import { OperationsContext } from "./RevoltClient";
 
 interface Props {
     auth?: boolean;
-    children: ReactNode | ReactNode[];
+    children: Children;
 }
 
 export const CheckAuth = (props: Props) => {
diff --git a/src/context/revoltjs/hooks.ts b/src/context/revoltjs/hooks.ts
index bb9fae1389013fa928be172cf54df6666b2f4312..e5e25a8629a49d33b8cf6d709d5da95eb4930033 100644
--- a/src/context/revoltjs/hooks.ts
+++ b/src/context/revoltjs/hooks.ts
@@ -11,8 +11,17 @@ export interface HookContext {
 export function useForceUpdate(context?: HookContext): HookContext {
     const client = useContext(AppContext);
     if (context) return context;
-    const [, updateState] = useState({});
-    return { client, forceUpdate: useCallback(() => updateState({}), []) };
+    const H = useState(undefined);
+    var updateState: (_: undefined) => void;
+    if (Array.isArray(H)) {
+        let [, u] = H;
+        updateState = u;
+    } else {
+        console.warn('Failed to construct using useState.');
+        console.warn(H);
+        updateState = ()=>{};
+    }
+    return { client, forceUpdate: useCallback(() => updateState(undefined), []) };
 }
 
 function useObject(type: string, id?: string | string[], context?: HookContext) {
diff --git a/src/lib/defer.ts b/src/lib/defer.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2ad2d46cba58ba9e179009410ada6c057062c339
--- /dev/null
+++ b/src/lib/defer.ts
@@ -0,0 +1,3 @@
+export function defer(cb: () => void) {
+    setTimeout(cb, 0);
+}
diff --git a/src/pages/channels/Channel.tsx b/src/pages/channels/Channel.tsx
index 4c731ce5453a40d1c8bd5f86d7bedb14c741b424..5e4ec842e22c9d129f7833ffb7f3d98b4bfd9866 100644
--- a/src/pages/channels/Channel.tsx
+++ b/src/pages/channels/Channel.tsx
@@ -4,6 +4,7 @@ import Header from "../../components/ui/Header";
 import { useRenderState } from "../../lib/renderer/Singleton";
 import { useChannel, useForceUpdate, useUsers } from "../../context/revoltjs/hooks";
 import { MessageArea } from "./messaging/MessageArea";
+import MessageBox from "../../components/common/messaging/MessageBox";
 
 const ChannelMain = styled.div`
     flex-grow: 1;
@@ -37,6 +38,7 @@ export default function Channel() {
             <ChannelMain>
                 <ChannelContent>
                     <MessageArea id={id} />
+                    <MessageBox channel={channel} />
                 </ChannelContent>
             </ChannelMain>
         </>
diff --git a/src/pages/friends/Friend.tsx b/src/pages/friends/Friend.tsx
index d27ee852560c97f79136baa5e18458507604cd6c..bcacd29953de3a8529268e0ad635d7a49a35d4a0 100644
--- a/src/pages/friends/Friend.tsx
+++ b/src/pages/friends/Friend.tsx
@@ -4,12 +4,12 @@ import styles from "./Friend.module.scss";
 import { useContext } from "preact/hooks";
 import { Children } from "../../types/Preact";
 import { X, Plus, Mail } from "@styled-icons/feather";
-import UserIcon from "../../components/common/UserIcon";
 import IconButton from "../../components/ui/IconButton";
 import { attachContextMenu } from "preact-context-menu";
 import { User, Users } from "revolt.js/dist/api/objects";
-import UserStatus from '../../components/common/UserStatus';
 import { stopPropagation } from "../../lib/stopPropagation";
+import UserIcon from "../../components/common/user/UserIcon";
+import UserStatus from '../../components/common/user/UserStatus';
 import { AppContext } from "../../context/revoltjs/RevoltClient";
 import { useIntermediate } from "../../context/intermediate/Intermediate";
 
diff --git a/src/pages/settings/Settings.module.scss b/src/pages/settings/Settings.module.scss
index 9497a959f45e0d66e67282cf8ebfb61a2026e356..dcb24eb4400a75d47749ff541ad70dabbf94de1c 100644
--- a/src/pages/settings/Settings.module.scss
+++ b/src/pages/settings/Settings.module.scss
@@ -185,25 +185,3 @@
         margin: auto;
     }
 }
-
-.textarea {
-    margin-bottom: 1em;
-    border-radius: 4px;
-    font-family: 'Courier New', Courier, monospace;
-
-    textarea {
-        resize: none;
-        padding: 12px;
-        min-height: 180px;
-        border-radius: 4px;
-        color: var(--foreground);
-        border: 2px solid transparent;
-        background: var(--secondary-background);
-        transition: border-color .2s ease-in-out;
-
-        &:focus {
-            outline: none;
-            border: 2px solid var(--accent);
-        }
-    }
-}
diff --git a/src/pages/settings/SettingsTextArea.tsx b/src/pages/settings/SettingsTextArea.tsx
deleted file mode 100644
index 2cf4a64a287610d2857979132b04f08c8b373691..0000000000000000000000000000000000000000
--- a/src/pages/settings/SettingsTextArea.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import styles from "./Settings.module.scss";
-import { TextArea, TextAreaProps } from "../../components/ui/TextArea";
-
-export function SettingsTextArea(props: TextAreaProps) {
-    return <TextArea {...props} className={styles.textarea} padding={16} />;
-}
diff --git a/src/pages/settings/channel/Overview.tsx b/src/pages/settings/channel/Overview.tsx
index 22eedca28beb3aa67f0b729e2ad48d4cc26fa900..a73a3fde855f2303c242d39f087b416db1b6661d 100644
--- a/src/pages/settings/channel/Overview.tsx
+++ b/src/pages/settings/channel/Overview.tsx
@@ -3,7 +3,7 @@ import styles from "./Panes.module.scss";
 import Button from "../../../components/ui/Button";
 import { Channels } from "revolt.js/dist/api/objects";
 import InputBox from "../../../components/ui/InputBox";
-import { SettingsTextArea } from "../SettingsTextArea";
+import TextArea from "../../../components/ui/TextArea";
 import { useContext, useEffect, useState } from "preact/hooks";
 import { AppContext } from "../../../context/revoltjs/RevoltClient";
 import { FileUploader } from "../../../context/revoltjs/FileUploads";
@@ -70,14 +70,14 @@ export function Overview({ channel }: Props) {
                     <Text id="app.main.groups.description" /> :
                     <Text id="app.main.servers.channel_description" /> }
             </h3>
-            <SettingsTextArea
-                maxRows={10}
-                minHeight={60}
+            <TextArea
+                // maxRows={10}
+                // minHeight={60}
                 maxLength={1024}
                 value={description}
                 placeholder={"Add a description..."}
-                onChange={content => {
-                    setDescription(content);
+                onChange={ev => {
+                    setDescription(ev.currentTarget.value);
                     if (!changed) setChanged(true)
                 }}
             />
diff --git a/src/pages/settings/panes/Account.tsx b/src/pages/settings/panes/Account.tsx
index 6147c25abad744da761869d7b31a54f7743b5d22..b3f7e61cc02970656523363fdfdd995f9a740def 100644
--- a/src/pages/settings/panes/Account.tsx
+++ b/src/pages/settings/panes/Account.tsx
@@ -6,11 +6,11 @@ import { Users } from "revolt.js/dist/api/objects";
 import { Link, useHistory } from "react-router-dom";
 import Overline from "../../../components/ui/Overline";
 import { AtSign, Key, Mail } from "@styled-icons/feather";
-import { useForceUpdate, useSelf } from "../../../context/revoltjs/hooks";
-import UserIcon from "../../../components/common/UserIcon";
 import { useContext, useEffect, useState } from "preact/hooks";
-import { ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient";
+import UserIcon from "../../../components/common/user/UserIcon";
+import { useForceUpdate, useSelf } from "../../../context/revoltjs/hooks";
 import { useIntermediate } from "../../../context/intermediate/Intermediate";
+import { ClientStatus, StatusContext } from "../../../context/revoltjs/RevoltClient";
 
 export function Account() {
     const { openScreen } = useIntermediate();
diff --git a/src/pages/settings/panes/Appearance.tsx b/src/pages/settings/panes/Appearance.tsx
index a746614323b97e43dc43d66d5cadee01acbc8e89..4fa442efa3802a2fefb7329e687014e5e8160391 100644
--- a/src/pages/settings/panes/Appearance.tsx
+++ b/src/pages/settings/panes/Appearance.tsx
@@ -2,8 +2,8 @@ import { Text } from "preact-i18n";
 import styles from "./Panes.module.scss";
 import { debounce } from "../../../lib/debounce";
 import Button from "../../../components/ui/Button";
+import TextArea from "../../../components/ui/TextArea";
 import InputBox from "../../../components/ui/InputBox";
-import { SettingsTextArea } from "../SettingsTextArea";
 import { connectState } from "../../../redux/connector";
 import { WithDispatcher } from "../../../redux/reducers";
 import ColourSwatches from "../../../components/ui/ColourSwatches";
@@ -267,11 +267,12 @@ export function Component(props: Props & WithDispatcher) {
                 <h3>
                     <Text id="app.settings.pages.appearance.custom_css" />
                 </h3>
-                <SettingsTextArea
-                    maxRows={20}
-                    minHeight={480}
+                <TextArea
+                    // maxRows={20}
+                    // minHeight={480}
+                    code
                     value={css}
-                    onChange={css => setCSS(css)}
+                    onChange={ev => setCSS(ev.currentTarget.value)}
                 />
             </details>
 
diff --git a/src/pages/settings/panes/Feedback.tsx b/src/pages/settings/panes/Feedback.tsx
index bda00cd2a3ba8a897cccf8bcffabca776833325e..a54c087d75cfd3847001dc0383f873f01c71df61 100644
--- a/src/pages/settings/panes/Feedback.tsx
+++ b/src/pages/settings/panes/Feedback.tsx
@@ -4,7 +4,7 @@ import { Localizer, Text } from "preact-i18n";
 import Radio from "../../../components/ui/Radio";
 import Button from "../../../components/ui/Button";
 import InputBox from "../../../components/ui/InputBox";
-import { SettingsTextArea } from "../SettingsTextArea";
+import TextArea from "../../../components/ui/TextArea";
 import { useSelf } from "../../../context/revoltjs/hooks";
 
 export function Feedback() {
@@ -80,12 +80,12 @@ export function Feedback() {
             <h3>
                 <Text id="app.settings.pages.feedback.describe" />
             </h3>
-            <SettingsTextArea
-                maxRows={10}
+            <TextArea
+                // maxRows={10}
                 value={description}
                 id="entry.685672624"
                 disabled={state === "sending"}
-                onChange={value => setDescription(value)}
+                onChange={ev => setDescription(ev.currentTarget.value)}
             />
             <Button type="submit" contrast>
                 <Text id="app.settings.pages.feedback.send" />
diff --git a/src/pages/settings/panes/Profile.tsx b/src/pages/settings/panes/Profile.tsx
index c87287f911720431e9fd1c31a97ed32b42f23924..aab0ae0b5efff39802b7d2c7ff7972ea089228b4 100644
--- a/src/pages/settings/panes/Profile.tsx
+++ b/src/pages/settings/panes/Profile.tsx
@@ -1,7 +1,7 @@
 import styles from "./Panes.module.scss";
 import Button from "../../../components/ui/Button";
 import { Users } from "revolt.js/dist/api/objects";
-import { SettingsTextArea } from "../SettingsTextArea";
+import TextArea from "../../../components/ui/TextArea";
 import { IntlContext, Text, translate } from "preact-i18n";
 import { useContext, useEffect, useState } from "preact/hooks";
 import { FileUploader } from "../../../context/revoltjs/FileUploads";
@@ -93,14 +93,14 @@ export function Profile() {
             <h3>
                 <Text id="app.settings.pages.profile.info" />
             </h3>
-            <SettingsTextArea
-                maxRows={10}
-                minHeight={200}
+            <TextArea
+                // maxRows={10}
+                // minHeight={200}
                 maxLength={2000}
                 value={profile?.content ?? ""}
                 disabled={typeof profile === "undefined"}
-                onChange={content => {
-                    setProfile({ ...profile, content })
+                onChange={ev => {
+                    setProfile({ ...profile, content: ev.currentTarget.value })
                     if (!changed) setChanged(true)
                 }}
                 placeholder={translate(
diff --git a/src/pages/settings/server/Invites.tsx b/src/pages/settings/server/Invites.tsx
index c1bca3dfedc6d52e7b52c95a68a8a36bd8598458..42144a96ffb5420627d8375a68704bccdb5244f8 100644
--- a/src/pages/settings/server/Invites.tsx
+++ b/src/pages/settings/server/Invites.tsx
@@ -2,8 +2,8 @@ import styles from './Panes.module.scss';
 import { XCircle } from "@styled-icons/feather";
 import { useEffect, useState } from "preact/hooks";
 import Preloader from "../../../components/ui/Preloader";
-import UserIcon from "../../../components/common/UserIcon";
 import IconButton from "../../../components/ui/IconButton";
+import UserIcon from "../../../components/common/user/UserIcon";
 import { getChannelName } from "../../../context/revoltjs/util";
 import { Invites as InvitesNS, Servers } from "revolt.js/dist/api/objects";
 import { useChannels, useForceUpdate, useUsers } from "../../../context/revoltjs/hooks";
diff --git a/src/pages/settings/server/Overview.tsx b/src/pages/settings/server/Overview.tsx
index d3ba3a3e9f7628266e649983548ce08f5f120dd4..3c8e2ec16748d468df1148fd1248e9d43187f143 100644
--- a/src/pages/settings/server/Overview.tsx
+++ b/src/pages/settings/server/Overview.tsx
@@ -2,7 +2,7 @@ import { Text } from "preact-i18n";
 import styles from './Panes.module.scss';
 import Button from "../../../components/ui/Button";
 import { Servers } from "revolt.js/dist/api/objects";
-import { SettingsTextArea } from "../SettingsTextArea";
+import TextArea from "../../../components/ui/TextArea";
 import InputBox from "../../../components/ui/InputBox";
 import { useContext, useEffect, useState } from "preact/hooks";
 import { AppContext } from "../../../context/revoltjs/RevoltClient";
@@ -65,14 +65,14 @@ export function Overview({ server }: Props) {
             <h3>
                 <Text id="app.main.servers.description" />
             </h3>
-            <SettingsTextArea
-                maxRows={10}
-                minHeight={60}
+            <TextArea
+                // maxRows={10}
+                // minHeight={60}
                 maxLength={1024}
                 value={description}
                 placeholder={"Add a topic..."}
-                onChange={content => {
-                    setDescription(content);
+                onChange={ev => {
+                    setDescription(ev.currentTarget.value);
                     if (!changed) setChanged(true)
                 }}
             />