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 ( + <> +
+ {itemExpandButton} + +
{uiName}
+
+
+
{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 @@ -197,4 +197,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; }