diff --git a/web/sidebar/community-drawer-item-community.react.js b/web/sidebar/community-drawer-item-community.react.js
new file mode 100644
--- /dev/null
+++ b/web/sidebar/community-drawer-item-community.react.js
@@ -0,0 +1,25 @@
+// @flow
+
+import classnames from 'classnames';
+import * as React from 'react';
+
+import css from './community-drawer-item.css';
+import type { DrawerItemProps } from './community-drawer-item.react.js';
+import CommunityDrawerItem from './community-drawer-item.react.js';
+
+function CommunityDrawerItemCommunity(props: DrawerItemProps): React.Node {
+ const classes = classnames({
+ [css.communityBase]: true,
+ [css.communityExpanded]: props.expanded,
+ });
+ return (
+
+
+
+ );
+}
+
+const MemoizedCommunityDrawerItemCommunity: React.ComponentType = React.memo(
+ CommunityDrawerItemCommunity,
+);
+export default MemoizedCommunityDrawerItemCommunity;
diff --git a/web/sidebar/community-drawer-item.css b/web/sidebar/community-drawer-item.css
new file mode 100644
--- /dev/null
+++ b/web/sidebar/community-drawer-item.css
@@ -0,0 +1,66 @@
+.threadEntry {
+ display: flex;
+ flex-direction: row;
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+
+.threadListContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.titleWrapper {
+ overflow: hidden;
+}
+
+.title {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ color: var(--drawer-item-color);
+ line-height: 24px;
+}
+
+.titleLevel0 {
+ font-size: var(--l-font-18);
+ font-weight: var(--semi-bold);
+}
+
+.titleLevel1,
+.titleLevel2 {
+ font-size: var(--m-font-16);
+ font-weight: var(--semi-bold);
+}
+
+.buttonContainer {
+ width: 24px;
+ align-items: center;
+ justify-content: center;
+ display: flex;
+}
+
+.chatItem {
+ margin-left: 16px;
+}
+
+.communityBase {
+ padding: 2px;
+ padding-right: 24px;
+ padding-left: 8px;
+ overflow: hidden;
+}
+
+.communityExpanded {
+ background-color: var(--drawer-open-community-bg);
+ border-top-right-radius: 8px;
+ border-bottom-right-radius: 8px;
+}
+
+.subchannelsButton {
+ margin-left: 24px;
+ margin-bottom: 6px;
+ margin-top: 4px;
+ display: flex;
+ align-items: center;
+}
diff --git a/web/sidebar/community-drawer-item.react.js b/web/sidebar/community-drawer-item.react.js
new file mode 100644
--- /dev/null
+++ b/web/sidebar/community-drawer-item.react.js
@@ -0,0 +1,135 @@
+// @flow
+
+import classnames from 'classnames';
+import * as React from 'react';
+
+import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react.js';
+import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js';
+
+import css from './community-drawer-item.css';
+import { ExpandButton } from './expand-buttons.react.js';
+import SubchannelsButton from './subchannels-button.react.js';
+import { useSelector } from '../redux/redux-utils.js';
+import {
+ useOnClickThread,
+ useThreadIsActive,
+} from '../selectors/thread-selectors.js';
+
+export type DrawerItemProps = {
+ +itemData: CommunityDrawerItemData,
+ +toggleExpanded: (threadID: string) => void,
+ +expanded: boolean,
+};
+
+function CommunityDrawerItem(props: DrawerItemProps): React.Node {
+ const {
+ itemData: { threadInfo, itemChildren, hasSubchannelsButton, labelStyle },
+ expanded,
+ toggleExpanded,
+ } = props;
+
+ const children = React.useMemo(() => {
+ if (!expanded) {
+ return null;
+ }
+ if (hasSubchannelsButton) {
+ return (
+
+
+
+ );
+ }
+ if (!itemChildren) {
+ return null;
+ }
+ return itemChildren.map(item => (
+
+ ));
+ }, [expanded, hasSubchannelsButton, itemChildren, threadInfo]);
+
+ const onExpandToggled = React.useCallback(
+ () => toggleExpanded(threadInfo.id),
+ [toggleExpanded, threadInfo.id],
+ );
+
+ const itemExpandButton = React.useMemo(() => {
+ if (itemChildren?.length === 0 && !hasSubchannelsButton) {
+ return (
+
+
+
+ );
+ }
+ return (
+
+
+
+ );
+ }, [itemChildren?.length, hasSubchannelsButton, onExpandToggled, expanded]);
+
+ const active = useThreadIsActive(threadInfo.id);
+ const isCreateMode = useSelector(
+ state => state.navInfo.chatMode === 'create',
+ );
+ const onClick = useOnClickThread(threadInfo);
+ const selectItemIfNotActiveCreation = React.useCallback(
+ (event: SyntheticEvent) => {
+ if (!isCreateMode || !active) {
+ onClick(event);
+ }
+ },
+ [isCreateMode, active, onClick],
+ );
+
+ const { uiName } = useResolvedThreadInfo(threadInfo);
+ const titleLabel = classnames(css.title, css[labelStyle]);
+
+ return (
+ <>
+
+ {children}
+ >
+ );
+}
+
+export type CommunityDrawerItemChatProps = {
+ +itemData: CommunityDrawerItemData,
+};
+
+function CommunityDrawerItemChat(
+ props: CommunityDrawerItemChatProps,
+): React.Node {
+ const [expanded, setExpanded] = React.useState(false);
+
+ const toggleExpanded = React.useCallback(() => {
+ setExpanded(isExpanded => !isExpanded);
+ }, []);
+
+ return (
+
+
+
+ );
+}
+
+const MemoizedCommunityDrawerItemChat: React.ComponentType = React.memo(
+ CommunityDrawerItemChat,
+);
+
+const MemoizedCommunityDrawerItem: React.ComponentType = React.memo(
+ CommunityDrawerItem,
+);
+
+export default MemoizedCommunityDrawerItem;
diff --git a/web/theme.css b/web/theme.css
--- a/web/theme.css
+++ b/web/theme.css
@@ -196,4 +196,6 @@
--purple-link: var(--violet-light-100);
--drawer-expand-button: var(--shades-black-60);
--drawer-expand-button-disabled: var(--shades-black-80);
+ --drawer-item-color: var(--shades-white-60);
+ --drawer-open-community-bg: #191919;
}