diff --git a/web/modals/chat/sidebar-list-modal.react.js b/web/modals/chat/sidebar-list-modal.react.js index 63b010937..c8aebb152 100644 --- a/web/modals/chat/sidebar-list-modal.react.js +++ b/web/modals/chat/sidebar-list-modal.react.js @@ -1,143 +1,143 @@ // @flow import { faTimesCircle } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import * as React from 'react'; import { sidebarInfoSelector } from 'lib/selectors/thread-selectors'; import SearchIndex from 'lib/shared/search-index'; import { threadSearchText } from 'lib/shared/thread-utils'; import type { ThreadInfo } from 'lib/types/thread-types'; import chatThreadListCSS from '../../chat/chat-thread-list.css'; import SidebarItem from '../../chat/sidebar-item.react'; import { useSelector } from '../../redux/redux-utils'; import globalCSS from '../../style.css'; import { MagnifyingGlass } from '../../vectors.react'; import { useModalContext } from '../modal-provider.react'; import Modal from '../modal.react'; type Props = { +threadInfo: ThreadInfo, }; function SidebarListModal(props: Props): React.Node { const { threadInfo } = props; const [searchState, setSearchState] = React.useState({ text: '', results: new Set(), }); const { popModal } = useModalContext(); const sidebarInfos = useSelector( state => sidebarInfoSelector(state)[threadInfo.id] ?? [], ); const userInfos = useSelector(state => state.userStore.userInfos); const listData = React.useMemo(() => { if (!searchState.text) { return sidebarInfos; } return sidebarInfos.filter(sidebarInfo => searchState.results.has(sidebarInfo.threadInfo.id), ); }, [sidebarInfos, searchState]); const sidebars = React.useMemo( () => listData.map(item => (
)), [popModal, listData], ); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, ); const searchIndex = React.useMemo(() => { const index = new SearchIndex(); for (const sidebarInfo of sidebarInfos) { const threadInfoFromSidebarInfo = sidebarInfo.threadInfo; index.addEntry( threadInfoFromSidebarInfo.id, threadSearchText(threadInfoFromSidebarInfo, userInfos, viewerID), ); } return index; }, [sidebarInfos, userInfos, viewerID]); React.useEffect(() => { setSearchState(curState => ({ ...curState, results: new Set(searchIndex.getSearchResults(curState.text)), })); }, [searchIndex]); const onChangeSearchText = React.useCallback( (event: SyntheticEvent) => { const searchText = event.currentTarget.value; setSearchState({ text: searchText, results: new Set(searchIndex.getSearchResults(searchText)), }); }, [searchIndex], ); const clearQuery = React.useCallback( (event: SyntheticEvent) => { event.preventDefault(); setSearchState({ text: '', results: [] }); }, [], ); let clearQueryButton = null; if (searchState.text) { clearQueryButton = ( ); } return ( - +
{clearQueryButton}
    {sidebars}
); } export default SidebarListModal; diff --git a/web/modals/modal.css b/web/modals/modal.css index 20248f59b..c9f609f67 100644 --- a/web/modals/modal.css +++ b/web/modals/modal.css @@ -1,79 +1,60 @@ -div.modal-overlay { +div.modalOverlay { position: fixed; left: 0; top: 0; - bottom: 0; + height: 100%; z-index: 4; width: 100%; - background-color: rgba(0, 0, 0, 0.4); + background-color: rgba(0, 0, 0, 0.9); display: flex; flex-direction: column; align-items: center; justify-content: center; - overflow: auto; -} -div.resizable-modal-overlay { - min-height: 60px; } -div.modal-container { - background: var(--bg); - background-size: 3000px 2000px; - max-width: 330px; + +div.modalContainer { border-radius: 15px; display: flex; - min-height: 0; - max-height: 500px; -} -div.large-modal-container { - max-width: 500px; -} -div.modal { - position: relative; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(0, 0, 0, 0.1); background-color: var(--modal-bg); - border-radius: 15px; - flex: 1; - display: flex; + border-radius: 8px; flex-direction: column; + margin: 20px; + overflow: hidden; } -div.large-modal-container div.modal { - width: 500px; + +div.modalContainerSmall { + width: 330px; + max-height: 500px; } -div.fixed-height-modal { - height: 100%; + +div.modalContainerLarge { + width: 500px; + max-height: 500px; } -span.modal-close { - float: right; - font-size: 32px; - font-weight: 300; - line-height: 30px; - color: var(--fg); + +span.modalClose { + display: flex; + color: var(--modal-close-color); } -span.modal-close:hover { + +span.modalClose:hover { cursor: pointer; + color: var(--modal-close-color-hover); } -div.modal-header { - padding: 32px 40px 16px 40px; -} -div.modal-header > h2 { - font-size: var(--xl-font-20); - font-weight: var(--bold); - color: var(--fg); + +div.modalHeader { display: flex; + justify-content: space-between; align-items: center; -} -div.modal-header > h2 svg { - padding-right: 8px; - display: flex; + padding: 32px 32px 0px 32px; } -@media only screen and (-webkit-min-device-pixel-ratio: 2), - only screen and (min--moz-device-pixel-ratio: 2), - only screen and (-o-min-device-pixel-ratio: 2/1), - only screen and (min-device-pixel-ratio: 2), - only screen and (min-resolution: 320dpi), - only screen and (min-resolution: 2dppx) { - div.modal-container { - background: var(--bg); - } +h2.title { + font-size: 20px; + font-weight: 500; + line-height: 32px; + color: var(--fg); + display: flex; + align-items: center; + column-gap: 8px; } diff --git a/web/modals/modal.react.js b/web/modals/modal.react.js index e0a4f8afc..3b66a8c52 100644 --- a/web/modals/modal.react.js +++ b/web/modals/modal.react.js @@ -1,120 +1,103 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import SWMansionIcon, { type Icon } from '../SWMansionIcon.react'; import css from './modal.css'; -export type ModalSize = 'small' | 'large'; +export type ModalSize = 'small' | 'large' | 'fit-content'; type Props = { - +name: React.Node, + +name: string, +icon?: Icon, +onClose: () => void, +withCloseButton?: boolean, +children?: React.Node, +size?: ModalSize, - +fixedHeight?: boolean, }; function Modal(props: Props): React.Node { const { size = 'small', children, onClose, - fixedHeight, name, icon, withCloseButton = true, } = props; const overlayRef = React.useRef(); const onBackgroundClick = React.useCallback( event => { if (event.target === overlayRef.current) { onClose(); } }, [onClose], ); const onKeyDown = React.useCallback( event => { if (event.keyCode === 27) { onClose(); } }, [onClose], ); React.useEffect(() => { if (overlayRef.current) { overlayRef.current.focus(); } }, []); - const overlayClasses = React.useMemo( - () => - classNames(css['modal-overlay'], { - [css['resizable-modal-overlay']]: !fixedHeight, - }), - [fixedHeight], - ); const modalContainerClasses = React.useMemo( () => - classNames(css['modal-container'], { - [css['large-modal-container']]: size === 'large', + classNames(css.modalContainer, { + [css.modalContainerLarge]: size === 'large', + [css.modalContainerSmall]: size === 'small', }), [size], ); - const modalClasses = React.useMemo( - () => - classNames(css['modal'], { - [css['fixed-height-modal']]: fixedHeight, - }), - [fixedHeight], - ); const cornerCloseButton = React.useMemo(() => { if (!withCloseButton) { return null; } return ( - + ); }, [onClose, withCloseButton]); const headerIcon = React.useMemo(() => { if (!icon) { return null; } return ; }, [icon]); return (
-
-
- {cornerCloseButton} -

- {headerIcon} - {name} -

-
- {children} +
+

+ {headerIcon} + {name} +

+ {cornerCloseButton}
+ {children}
); } export default Modal; diff --git a/web/theme.css b/web/theme.css index 77fadb50e..d0a15e53a 100644 --- a/web/theme.css +++ b/web/theme.css @@ -1,146 +1,148 @@ :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-danger: var(--error-primary); --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); --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-of-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); }