diff --git a/web/modals/threads/members/members-modal.css b/web/modals/threads/members/members-modal.css
index 13a668ab8..394566adc 100644
--- a/web/modals/threads/members/members-modal.css
+++ b/web/modals/threads/members/members-modal.css
@@ -1,114 +1,127 @@
div.modalContentContainer {
width: 383px;
height: 617px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ row-gap: 16px;
+}
+
+div.membersListTabs {
+ flex: 1;
+ overflow: hidden;
+}
+
+div.addNewMembers button {
+ width: 100%;
}
div.membersList {
overflow: auto;
padding: 8px 0;
color: var(--members-modal-member-text);
}
div.noScroll {
overflow: hidden;
}
div.memberContainer {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 8px 16px;
}
div.memberContainer:hover {
color: var(--members-modal-member-text-hover);
}
div.memberContainerWithMenuOpen {
color: var(--members-modal-member-text-hover);
}
div.memberInfo {
font-size: var(--l-font-18);
display: flex;
align-items: center;
gap: 10px;
}
div.memberAction {
position: relative;
}
h5.memberletterHeader {
margin: 16px;
color: var(--members-modal-member-text);
font-size: var(--s-font-14);
}
div.noUsers {
padding-top: 16px;
text-align: center;
}
div.addMembersContent {
display: flex;
flex-direction: column;
overflow: auto;
color: var(--fg);
row-gap: 16px;
width: 383px;
height: 617px;
}
div.addMembersListContainer {
overflow: auto;
flex: 1;
}
div.addMembersFooter {
display: flex;
justify-content: end;
column-gap: 16px;
}
div.addMemberItemsGroupHeader {
font-size: var(--s-font-14);
color: var(--add-members-group-header-color);
margin: 16px;
}
button.addMemberItem {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
color: var(--add-members-item-color);
font-size: var(--l-font-18);
background-color: transparent;
border: none;
width: 100%;
}
button.addMemberItem:hover {
color: var(--add-members-item-color-hover);
}
button.addMemberItem:disabled {
color: var(--add-members-item-disabled-color);
cursor: not-allowed;
}
button.addMemberItem:hover:disabled {
color: var(--add-members-item-disabled-color-hover);
}
button.addMemberItem .label {
padding: 8px 16px;
}
button.addMemberItem .danger {
color: var(--add-members-remove-pending-color);
}
button.addMemberItem:hover .danger {
color: var(--add-members-remove-pending-color-hover);
}
diff --git a/web/modals/threads/members/members-modal.react.js b/web/modals/threads/members/members-modal.react.js
index 0be54a27f..c5aec0b1c 100644
--- a/web/modals/threads/members/members-modal.react.js
+++ b/web/modals/threads/members/members-modal.react.js
@@ -1,106 +1,141 @@
// @flow
import * as React from 'react';
import { threadInfoSelector } from 'lib/selectors/thread-selectors';
import { userStoreSearchIndex } from 'lib/selectors/user-selectors';
-import { memberHasAdminPowers, memberIsAdmin } from 'lib/shared/thread-utils';
-import { type RelativeMemberInfo } from 'lib/types/thread-types';
+import {
+ memberHasAdminPowers,
+ memberIsAdmin,
+ threadHasPermission,
+} from 'lib/shared/thread-utils';
+import {
+ type RelativeMemberInfo,
+ threadPermissions,
+} from 'lib/types/thread-types';
+import Button from '../../../components/button.react';
import Tabs from '../../../components/tabs.react';
import { useSelector } from '../../../redux/redux-utils';
+import { useModalContext } from '../../modal-provider.react';
import SearchModal from '../../search-modal.react';
+import AddMembersModal from './add-members-modal.react';
import ThreadMembersList from './members-list.react';
import css from './members-modal.css';
type ContentProps = {
+searchText: string,
+threadID: string,
};
function ThreadMembersModalContent(props: ContentProps): React.Node {
const { threadID, searchText } = props;
const [tab, setTab] = React.useState<'All Members' | 'Admins'>('All Members');
const threadInfo = useSelector(state => threadInfoSelector(state)[threadID]);
const { members: threadMembersNotFiltered } = threadInfo;
const userSearchIndex = useSelector(userStoreSearchIndex);
const userIDs = React.useMemo(
() => userSearchIndex.getSearchResults(searchText),
[searchText, userSearchIndex],
);
const allMembers = React.useMemo(
() =>
threadMembersNotFiltered.filter(
(member: RelativeMemberInfo) =>
searchText.length === 0 || userIDs.includes(member.id),
),
[searchText.length, threadMembersNotFiltered, userIDs],
);
const adminMembers = React.useMemo(
() =>
allMembers.filter(
(member: RelativeMemberInfo) =>
memberIsAdmin(member, threadInfo) || memberHasAdminPowers(member),
),
[allMembers, threadInfo],
);
const allUsersTab = React.useMemo(
() => (