diff --git a/web/chat/chat-thread-composer.css b/web/chat/chat-thread-composer.css new file mode 100644 index 000000000..33fbc77a1 --- /dev/null +++ b/web/chat/chat-thread-composer.css @@ -0,0 +1,72 @@ +div.threadSearchContainer { + background-color: var(--thread-creation-search-container-bg); + color: var(--fg); + display: flex; + flex-direction: column; + max-height: 50%; + overflow: auto; + flex-shrink: 0; +} + +div.fullHeight { + flex-grow: 1; + max-height: 100%; +} + +div.userSelectedTags { + display: flex; + flex-wrap: wrap; + flex-direction: row; + align-items: center; + gap: 4px; + padding: 4px 12px; + margin-bottom: 8px; +} + +div.searchRow { + display: flex; + flex-direction: row; + align-items: center; + margin-right: 8px; +} + +div.searchField { + flex-grow: 1; +} + +div.closeSearch { + cursor: pointer; + display: flex; + align-items: center; + color: var(--thread-creation-close-search-color); + margin: 0 8px; +} + +ul.searchResultsContainer { + display: flex; + flex-direction: column; + overflow: auto; + padding: 0 12px 8px; +} + +li.searchResultsItem { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: 8px 12px; + cursor: pointer; +} + +li.searchResultsItem:hover { + background-color: var(--thread-creation-search-item-bg-hover); +} + +div.userName { + color: var(--fg); +} + +div.userInfo { + font-style: italic; + color: var(--thread-creation-search-item-info-color); +} diff --git a/web/chat/chat-thread-composer.react.js b/web/chat/chat-thread-composer.react.js new file mode 100644 index 000000000..10ded9130 --- /dev/null +++ b/web/chat/chat-thread-composer.react.js @@ -0,0 +1,124 @@ +// @flow +import classNames from 'classnames'; +import * as React from 'react'; + +import { userSearchIndexForPotentialMembers } from 'lib/selectors/user-selectors'; +import { getPotentialMemberItems } from 'lib/shared/search-utils'; +import type { AccountUserInfo, UserListItem } from 'lib/types/user-types'; + +import Label from '../components/label.react'; +import Search from '../components/search.react'; +import type { InputState } from '../input/input-state'; +import { useSelector } from '../redux/redux-utils'; +import SWMansionIcon from '../SWMansionIcon.react'; +import css from './chat-thread-composer.css'; + +type Props = { + +userInfoInputArray: $ReadOnlyArray, + +otherUserInfos: { [id: string]: AccountUserInfo }, + +threadID: string, + +inputState: InputState, +}; + +function ChatThreadComposer(props: Props): React.Node { + const { userInfoInputArray, otherUserInfos } = props; + + const [usernameInputText, setUsernameInputText] = React.useState(''); + + const userSearchIndex = useSelector(userSearchIndexForPotentialMembers); + + const userInfoInputIDs = React.useMemo( + () => userInfoInputArray.map(userInfo => userInfo.id), + [userInfoInputArray], + ); + + const userListItems = React.useMemo( + () => + getPotentialMemberItems( + usernameInputText, + otherUserInfos, + userSearchIndex, + userInfoInputIDs, + ), + [usernameInputText, otherUserInfos, userSearchIndex, userInfoInputIDs], + ); + + // eslint-disable-next-line no-unused-vars + const onSelectUserFromSearch = React.useCallback((id: string) => {}, []); + // eslint-disable-next-line no-unused-vars + const onRemoveUserFromSelected = React.useCallback((id: string) => {}, []); + + const userSearchResultList = React.useMemo(() => { + if ( + !userListItems.length || + (!usernameInputText && userInfoInputArray.length) + ) { + return null; + } + + return ( + + ); + }, [ + onSelectUserFromSearch, + userInfoInputArray.length, + userListItems, + usernameInputText, + ]); + + const hideSearch = React.useCallback(() => {}, []); + + const tagsList = React.useMemo(() => { + if (!userInfoInputArray?.length) { + return null; + } + const labels = userInfoInputArray.map(user => { + return ( + + ); + }); + return
{labels}
; + }, [userInfoInputArray, onRemoveUserFromSelected]); + + const threadSearchContainerStyles = React.useMemo( + () => + classNames(css.threadSearchContainer, { + [css.fullHeight]: !userInfoInputArray.length, + }), + [userInfoInputArray.length], + ); + + return ( +
+
+
+ +
+
+ +
+
+ {tagsList} + {userSearchResultList} +
+ ); +} + +export default ChatThreadComposer; diff --git a/web/theme.css b/web/theme.css index be41376f5..e8ce6f9b6 100644 --- a/web/theme.css +++ b/web/theme.css @@ -1,172 +1,176 @@ :root { /* Never use color values defined here directly in CSS. Add color variables to "Color Theme" below The reason we never use color values defined here directly in CSS is 1. It makes changing themes from light / dark / user generated impossible. 2. Gives the programmer context into the color being used. 3. If our color system changes it's much easier to change color values in one place. Add a color value to the theme below, and then use it in your CSS. naming convention: - bg: background. - fg: foreground. - color: text-color */ --shades-white-100: #ffffff; --shades-white-90: #f5f5f5; --shades-white-80: #ebebeb; --shades-white-70: #e0e0e0; --shades-white-60: #cccccc; --shades-black-100: #0a0a0a; --shades-black-90: #1f1f1f; --shades-black-80: #404040; --shades-black-70: #666666; --shades-black-60: #808080; --violet-dark-100: #7e57c2; --violet-dark-80: #6d49ab; --violet-dark-60: #563894; --violet-dark-40: #44297a; --violet-dark-20: #331f5c; --violet-light-100: #ae94db; --violet-light-80: #b9a4df; --violet-light-60: #d3c6ec; --violet-light-40: #e8e0f5; --violet-light-20: #f3f0fa; --success-light-10: #d5f6e3; --success-light-50: #6cdf9c; --success-primary: #00c853; --success-dark-50: #029841; --success-dark-90: #034920; --error-light-10: #feebe6; --error-light-50: #f9947b; --error-primary: #f53100; --error-dark-50: #b62602; --error-dark-90: #4f1203; --bg: var(--shades-black-100); --fg: var(--shades-white-100); --color-disabled: var(--shades-black-60); --text-input-bg: var(--shades-black-80); --text-input-color: var(--shades-white-60); --text-input-placeholder: var(--shades-white-60); --border: var(--shades-black-80); --error: var(--error-primary); --success: var(--success-dark-50); /* Color Theme */ --btn-bg-primary: var(--violet-dark-100); --btn-bg-primary-hover: var(--violet-dark-80); --btn-bg-primary-disabled: var(--shades-black-80); --btn-bg-secondary: var(--shades-black-90); --btn-bg-secondary-hover: var(--shades-black-80); --btn-bg-secondary-disabled: var(--shades-black-90); --btn-bg-danger: var(--error-primary); --btn-bg-danger-hover: var(--error-dark-50); --btn-bg-danger-disabled: var(--shades-black-80); --btn-disabled-color: var(--shades-black-60); --chat-bg: var(--violet-dark-80); --chat-confirmation-icon: var(--violet-dark-100); --keyserver-selection: var(--violet-dark-60); --thread-selection: var(--violet-light-80); --thread-hover-bg: var(--shades-black-90); --thread-active-bg: var(--shades-black-80); --chat-timestamp-color: var(--shades-black-60); --tool-tip-bg: var(--shades-black-80); --tool-tip-color: var(--shades-white-60); --border-color: var(--shades-black-80); --calendar-chevron: var(--shades-black-60); --calendar-day-bg: var(--shades-black-60); --calendar-day-selected-color: var(--violet-dark-80); --community-bg: var(--shades-black-90); --community-settings-selected: var(--violet-dark-60); --unread-bg: var(--error-primary); --settings-btn-bg: var(--violet-dark-100); --modal-bg: var(--shades-black-90); --modal-fg: var(--shades-white-60); --join-bg: var(--shades-black-90); --help-color: var(--shades-black-60); --breadcrumb-color: var(--shades-white-60); --breadcrumb-color-unread: var(--shades-white-60); --btn-secondary-border: var(--shades-black-60); --thread-color-read: var(--shades-black-60); --thread-from-color-read: var(--shades-black-80); --thread-last-message-color-read: var(--shades-black-60); --relationship-button-green: var(--success-dark-50); --relationship-button-red: var(--error-primary); --relationship-button-text: var(--fg); --disconnected-bar-alert-bg: var(--error-dark-50); --disconnected-bar-alert-color: var(--shades-white-100); --disconnected-bar-connecting-bg: var(--shades-white-70); --disconnected-bar-connecting-color: var(--shades-black-100); --permission-color: var(--shades-white-60); --thread-top-bar-color: var(--shades-white-100); --thread-top-bar-menu-color: var(--shades-white-70); --thread-ancestor-keyserver-border: var(--shades-black-70); --thread-ancestor-color-light: var(--shades-white-70); --thread-ancestor-color-dark: var(--shades-black-100); --thread-ancestor-separator-color: var(--shades-white-60); --text-message-default-background: var(--shades-black-80); --message-action-tooltip-bg: var(--shades-black-90); --menu-bg: var(--shades-black-90); --menu-bg-light: var(--shades-black-80); --menu-separator-color: var(--shades-black-80); --menu-color: var(--shades-black-60); --menu-color-light: var(--shades-white-60); --menu-color-hover: var(--shades-white-100); --menu-color-dangerous: var(--error-primary); --menu-color-dangerous-hover: var(--error-light-50); --app-list-icon-read-only-color: var(--shades-black-60); --app-list-icon-enabled-color: var(--success-primary); --app-list-icon-disabled-color: var(--shades-white-80); --account-settings-label: var(--shades-black-60); --account-button-color: var(--violet-dark-100); --chat-thread-list-color-active: var(--shades-white-60); --chat-thread-list-menu-color: var(--shades-white-60); --chat-thread-list-menu-bg: var(--shades-black-80); --chat-thread-list-menu-active-color: var(--shades-white-60); --chat-thread-list-menu-active-bg: var(--shades-black-90); --search-clear-color: var(--shades-white-100); --search-clear-bg: var(--shades-black-70); --search-input-color: var(--shades-white-100); --search-input-placeholder: var(--shades-black-60); --search-icon-color: var(--shades-black-60); --tabs-header-active-color: var(--shades-white-100); --tabs-header-active-border: var(--violet-light-100); --tabs-header-background-color: var(--shades-black-60); --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); --subchannels-modal-color: var(--shades-black-60); --subchannels-modal-color-hover: var(--shades-white-100); --color-selector-active-bg: var(--shades-black-80); --relationship-modal-color: var(--shades-black-60); --arrow-extension-color: var(--shades-black-60); --modal-close-color: var(--shades-black-60); --modal-close-color-hover: var(--shades-white-100); --add-members-group-header-color: var(--shades-black-60); --add-members-item-color: var(--shades-black-60); --add-members-item-color-hover: var(--shades-white-100); --add-members-item-disabled-color: var(--shades-black-80); --add-members-item-disabled-color-hover: var(--shades-black-60); --add-members-remove-pending-color: var(--error-primary); --add-members-remove-pending-color-hover: var(--error-light-50); --radio-border: var(--shades-black-70); --radio-color: var(--shades-white-60); --notification-settings-option-selected-bg: var(--shades-black-80); --notification-settings-option-title-color: var(--shades-white-90); --notification-settings-option-color: var(--shades-white-60); --notification-settings-option-invalid-color: var(--shades-black-80); --notification-settings-option-invalid-selected-color: var(--shades-black-60); --danger-zone-subheading-color: var(--shades-white-60); --danger-zone-explanation-color: var(--shades-black-60); + --thread-creation-search-container-bg: var(--shades-black-90); + --thread-creation-close-search-color: var(--shades-black-60); + --thread-creation-search-item-bg-hover: var(--shades-black-80); + --thread-creation-search-item-info-color: var(--shades-black-60); }