diff --git a/web/chat/chat-thread-list.css b/web/chat/chat-thread-list.css index a7cd47286..800fe84f4 100644 --- a/web/chat/chat-thread-list.css +++ b/web/chat/chat-thread-list.css @@ -1,324 +1,290 @@ div.thread { display: flex; flex-direction: row; align-items: flex-start; padding-top: 4px; padding-bottom: 4px; padding-right: 10px; cursor: pointer; } div.threadListSidebar { display: flex; flex-direction: row; align-items: flex-start; padding-bottom: 4px; padding-left: 16px; padding-right: 10px; position: relative; cursor: pointer; } div.threadListSidebar > svg { position: absolute; top: -13px; left: 30px; } div.thread:first-child { padding-top: 6px; } div.activeThread, div.threadListSidebar:hover { background: var(--thread-active-bg); } div.activeThread :is(div.dark, .lastMessage span.read, .title) { color: var(--fg); } div.activeThread .lastMessage.read { color: var(--fg); } div.activeThread.thread:hover { background: var(--thread-active-bg); } div.thread:hover { background: var(--thread-hover-bg); } div.title { flex: 1; font-size: var(--m-font-16); font-weight: var(--semi-bold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--thread-color-read); line-height: var(--line-height-text); } div.threadButton { flex: 1; cursor: pointer; overflow: hidden; padding-left: 12px; } a.threadButton + div { display: flex; flex-direction: column; padding-top: 8px; } .threadButtonSidebar { flex: 1; cursor: pointer; overflow: hidden; padding-left: 8px; } p.breadCrumbs { display: flex; padding: 8px 0 2px 0; font-size: var(--xs-font-12); font-weight: var(--normal); color: var(--breadcrumb-color); } p.breadCrumbs.unread { color: var(--breadcrumb-color-unread); } span.breadCrumb { display: flex; align-items: center; white-space: nowrap; text-overflow: ellipsis; } div.colorContainer { display: flex; padding-top: 8px; } div.spacer, div.colorSplotch { height: 42px; width: 42px; border-radius: 1.68px; } div.lastActivity { font-size: var(--xxs-font-10); color: var(--fg); line-height: 1.5; font-weight: var(--semi-bold); white-space: nowrap; } div.lastMessage { font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: var(--line-height-text); padding-bottom: 8px; } div.threadRow > .lastMessage { color: var(--thread-last-message-color-read); font-size: var(--s-font-14); } div.unread { color: var(--fg); font-weight: var(--semi-bold); } div.lastMessage.unread { color: var(--fg); } div.dark { color: var(--thread-color-read); } .read { color: var(--thread-from-color-read); } div.dotContainer { display: flex; align-items: center; justify-content: center; width: 16px; } div.unreadDot { height: 4px; width: 4px; background: var(--fg); border-radius: 15px; align-self: center; } div.italic { font-style: italic; } div.sidebarTitle { flex: 1; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--thread-color-read); align-self: flex-start; } div.sidebarTitle.unread { color: var(--fg); } div.sidebarLastActivity { white-space: nowrap; font-size: var(--xxs-font-10); line-height: var(--line-height-text); font-weight: var(--semi-bold); } svg.sidebarIcon { color: var(--thread-color-read); padding: 0 6px; font-size: 20px; } div.sidebar .menu > button svg { font-size: 16px; color: var(--thread-color-read); } div.sidebar .menu { opacity: 0; } div.sidebar:hover .menu { display: flex; align-self: flex-end; opacity: 1; } .menu { position: relative; display: flex; justify-content: flex-end; } .menu > button { background-color: transparent; color: var(--thread-color-read); border: none; cursor: pointer; display: flex; align-items: center; } .menu > button:focus { outline: none; } .menuContent { display: none; position: absolute; top: calc(100% + 1px); right: 0; z-index: 1; width: max-content; overflow: hidden; background-color: #eeeeee; border-radius: 5px; box-shadow: 1px 1px 5px 2px #00000022; } .menuContentVisible { display: block; } button.menuContent { border: none; cursor: pointer; padding: 10px; font-size: 16px; } button.menuContent:hover { background-color: #dddddd; } ul.list { margin: 5px 3px 10px 0px; overflow: auto; } div.search { display: flex; background-color: #dddddd; border-radius: 5px; padding: 3px 5px; align-items: center; } svg.searchVector { fill: #aaaaaa; height: 22px; width: 22px; padding: 0 3px; margin-left: 8px; } div.search > input { color: black; padding: 0; border: none; background-color: #dddddd; font-weight: 600; font-size: 15px; flex-grow: 1; margin-left: 3px; } div.search > input:focus { outline: none; } svg.clearQuery { font-size: 15px; padding-bottom: 1px; padding-right: 2px; color: #aaaaaa; } svg.clearQuery:hover { font-size: 15px; padding-bottom: 1px; padding-right: 2px; color: white; } div.spacer { height: 6px; } div.emptyItem { padding: 10px; font-size: 16px; text-align: center; white-space: pre-wrap; color: var(--fg); } div.threadListContainer { display: flex; flex-direction: column; } - -div.searchContainer { - background-color: var(--text-input-bg); - display: flex; - align-items: center; - margin: 1rem; -} - -input.searchInput { - background-color: var(--text-input-bg); - font-size: var(--s-font-14); - padding: 1rem; - flex: 1; - border: none; - color: var(--text-input-color); - outline: none; -} - -input.searchInput::placeholder { - color: var(--text-input-placeholder); -} - -button.clearSearch { - color: var(--text-input-color); - transition: ease-in-out 0.15s; - border: none; - padding: 0 1rem; - font-size: var(--m-font-16); - background: none; -} - -button.clearSearchDisabled { - opacity: 0; -} diff --git a/web/chat/chat-thread-list.react.js b/web/chat/chat-thread-list.react.js index 3d56bea22..dda220a3f 100644 --- a/web/chat/chat-thread-list.react.js +++ b/web/chat/chat-thread-list.react.js @@ -1,49 +1,53 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { emptyItemText } from 'lib/shared/thread-utils'; +import Search from '../components/search.react'; import ChatThreadListItem from './chat-thread-list-item.react'; import css from './chat-thread-list.css'; import { ThreadListContext } from './thread-list-provider'; -import ThreadListSearch from './thread-list-search.react'; function ChatThreadList(): React.Node { const threadListContext = React.useContext(ThreadListContext); invariant( threadListContext, 'threadListContext should be set in ChatThreadList', ); const { activeTab, threadList, setSearchText, searchText, } = threadListContext; const isBackground = activeTab === 'Background'; const threadComponents: React.Node[] = React.useMemo(() => { const threads = threadList.map(item => ( )); if (threads.length === 0 && isBackground) { threads.push(); } return threads; }, [threadList, isBackground]); return (
- +
{threadComponents}
); } function EmptyItem() { return
{emptyItemText}
; } export default ChatThreadList; diff --git a/web/chat/clear-search-button.react.js b/web/components/clear-search-button.react.js similarity index 94% rename from web/chat/clear-search-button.react.js rename to web/components/clear-search-button.react.js index 55e1af6c4..69fb39555 100644 --- a/web/chat/clear-search-button.react.js +++ b/web/components/clear-search-button.react.js @@ -1,27 +1,27 @@ // @flow import { faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import * as React from 'react'; -import css from './chat-thread-list.css'; +import css from './search.css'; type ClearSearchButtonProps = { +active: boolean, +onClick: () => void, }; function ClearSearchButton(props: ClearSearchButtonProps): React.Node { const { active, onClick } = props; const searchClassNames = classNames(css.clearSearch, { [css.clearSearchDisabled]: !active, }); return ( ); } export default ClearSearchButton; diff --git a/web/components/search.css b/web/components/search.css new file mode 100644 index 000000000..800eeda7e --- /dev/null +++ b/web/components/search.css @@ -0,0 +1,33 @@ +div.searchContainer { + background-color: var(--text-input-bg); + display: flex; + align-items: center; + margin: 1rem; +} + +input.searchInput { + background-color: var(--text-input-bg); + font-size: var(--s-font-14); + padding: 1rem; + flex: 1; + border: none; + color: var(--text-input-color); + outline: none; +} + +input.searchInput::placeholder { + color: var(--text-input-placeholder); +} + +button.clearSearch { + color: var(--text-input-color); + transition: ease-in-out 0.15s; + border: none; + padding: 0 1rem; + font-size: var(--m-font-16); + background: none; +} + +button.clearSearchDisabled { + opacity: 0; +} diff --git a/web/chat/thread-list-search.react.js b/web/components/search.react.js similarity index 73% rename from web/chat/thread-list-search.react.js rename to web/components/search.react.js index d7780db5e..fa49b062d 100644 --- a/web/chat/thread-list-search.react.js +++ b/web/components/search.react.js @@ -1,43 +1,44 @@ // @flow import * as React from 'react'; -import css from './chat-thread-list.css'; import ClearSearchButton from './clear-search-button.react'; +import css from './search.css'; -type ThreadListSearchProps = { +type Props = { +searchText: string, +onChangeText: (searchText: string) => mixed, + +placeholder?: string, }; -function ThreadListSearch(props: ThreadListSearchProps): React.Node { - const { searchText, onChangeText } = props; +function Search(props: Props): React.Node { + const { searchText, onChangeText, placeholder } = props; const showClearButton = !!searchText; const onClear = React.useCallback(() => { onChangeText(''); }, [onChangeText]); const onChange = React.useCallback( event => { onChangeText(event.target.value); }, [onChangeText], ); return (
); } -export default ThreadListSearch; +export default Search;