diff --git a/web/modals/threads/members/members-list.react.js b/web/modals/threads/members/members-list.react.js new file mode 100644 --- /dev/null +++ b/web/modals/threads/members/members-list.react.js @@ -0,0 +1,78 @@ +// @flow + +import classNames from 'classnames'; +import _ from 'lodash'; +import * as React from 'react'; + +import { stringForUser } from 'lib/shared/user-utils'; +import { + type ThreadInfo, + type RelativeMemberInfo, +} from 'lib/types/thread-types'; + +import ThreadMember from './member.react'; +import css from './members-modal.css'; + +type Props = { + +threadInfo: ThreadInfo, + +threadMembers: $ReadOnlyArray, +}; + +function ThreadMembersList(props: Props): React.Node { + const { threadMembers, threadInfo } = props; + const [openMenus, setOpenMenus] = React.useState([]); + const userExists = threadMembers.length > 0; + + const groupedByFirstLetterMembers = React.useMemo( + () => _.groupBy(threadMembers, member => stringForUser(member)[0]), + [threadMembers], + ); + + const groupedMembersList = React.useMemo( + () => + _.toPairs(groupedByFirstLetterMembers) + .sort((a, b) => a[0].localeCompare(b[0])) + .map(([letter, users]) => { + const userList = users.map((user: RelativeMemberInfo) => ( + { + if (menuOpen) { + setOpenMenus(menus => [...menus, user.id]); + } else { + setOpenMenus(menus => menus.filter(id => id !== user.id)); + } + }} + /> + )); + const letterHeader = ( +
+ {letter.toUpperCase()} +
+ ); + return ( + + {letterHeader} + {userList} + + ); + }), + [groupedByFirstLetterMembers, threadInfo], + ); + let content = groupedMembersList; + if (!userExists) { + content = ( +
+ No matching users were found in the thread! +
+ ); + } + const membersListClasses = classNames(css.membersList, { + [css.noScroll]: !!openMenus.length, + }); + return
{content}
; +} + +export default ThreadMembersList; diff --git a/web/modals/threads/members/members-modal.css b/web/modals/threads/members/members-modal.css --- a/web/modals/threads/members/members-modal.css +++ b/web/modals/threads/members/members-modal.css @@ -1,3 +1,13 @@ +div.membersList { + overflow: scroll; + padding: 8px 0; + color: var(--members-modal-member-text); +} + +div.noScroll { + overflow: hidden; +} + div.memberContainer { display: flex; flex-direction: row; @@ -23,3 +33,14 @@ div.memberAction { position: relative; } + +div.memberletterHeader { + margin: 16px; + color: var(--members-modal-member-text); + font-size: var(--s-font-14); +} + +div.noUsers { + padding-top: 16px; + text-align: center; +} diff --git a/web/theme.css b/web/theme.css --- a/web/theme.css +++ b/web/theme.css @@ -122,6 +122,8 @@ --tabs-header-background-border: var(--shades-black-80); --tabs-header-background-color-hover: var(--shades-white-80); --tabs-header-background-border-hover: var(--shades-black-70); + --members-modal-member-text: var(--shades-black-60); + --members-modal-member-text-hover: var(--shades-white-100); --label-default-bg: var(--violet-dark-80); --label-default-color: var(--shades-white-80); }