diff --git a/web/sidebar/community-drawer-item-handler.react.js b/web/sidebar/community-drawer-item-handler.react.js index a72ffed92..815c892e6 100644 --- a/web/sidebar/community-drawer-item-handler.react.js +++ b/web/sidebar/community-drawer-item-handler.react.js @@ -1,5 +1,6 @@ // @flow export type CommunityDrawerItemHandler = { +onClick: (event: SyntheticEvent) => void, + +isActive: boolean, }; diff --git a/web/sidebar/community-drawer-item-handlers.react.js b/web/sidebar/community-drawer-item-handlers.react.js index eaeb4cc28..4fd5bb9c6 100644 --- a/web/sidebar/community-drawer-item-handlers.react.js +++ b/web/sidebar/community-drawer-item-handlers.react.js @@ -1,70 +1,81 @@ // @flow import * as React from 'react'; import { useDispatch } from 'react-redux'; import { updateCalendarThreadFilter, calendarThreadFilterTypes, } from 'lib/types/filter-types.js'; import type { ThreadInfo } from 'lib/types/thread-types'; import type { CommunityDrawerItemHandler } from './community-drawer-item-handler.react.js'; -import { useOnClickThread } from '../selectors/thread-selectors.js'; +import { + useOnClickThread, + useThreadIsActive, +} from '../selectors/thread-selectors.js'; import type { NavigationTab } from '../types/nav-types'; type HandlerProps = { +setHandler: (handler: CommunityDrawerItemHandler) => void, +threadInfo: ThreadInfo, }; function ChatDrawerItemHandler(props: HandlerProps): React.Node { const { setHandler, threadInfo } = props; const onClick = useOnClickThread(threadInfo); - const handler = React.useMemo(() => ({ onClick }), [onClick]); + const isActive = useThreadIsActive(threadInfo.id); + const handler = React.useMemo(() => ({ onClick, isActive }), [ + isActive, + onClick, + ]); React.useEffect(() => { setHandler(handler); }, [handler, setHandler]); return null; } function CalendarDrawerItemHandler(props: HandlerProps): React.Node { const { setHandler, threadInfo } = props; const dispatch = useDispatch(); const onClick = React.useCallback( () => dispatch({ type: updateCalendarThreadFilter, payload: { type: calendarThreadFilterTypes.THREAD_LIST, threadIDs: [threadInfo.id], }, }), [dispatch, threadInfo.id], ); - const handler = React.useMemo(() => ({ onClick }), [onClick]); + const isActive = false; + const handler = React.useMemo(() => ({ onClick, isActive }), [ + onClick, + isActive, + ]); React.useEffect(() => { setHandler(handler); }, [handler, setHandler]); return null; } const communityDrawerItemHandlers: { +[tab: NavigationTab]: React.ComponentType, } = Object.freeze({ chat: ChatDrawerItemHandler, calendar: CalendarDrawerItemHandler, }); function getCommunityDrawerItemHandler( tab: NavigationTab, ): React.ComponentType { return communityDrawerItemHandlers[tab] ?? ChatDrawerItemHandler; } export { getCommunityDrawerItemHandler }; diff --git a/web/sidebar/community-drawer-item.css b/web/sidebar/community-drawer-item.css index 8a1f2ea0d..4dc74d889 100644 --- a/web/sidebar/community-drawer-item.css +++ b/web/sidebar/community-drawer-item.css @@ -1,61 +1,69 @@ .threadEntry { display: flex; flex-direction: row; padding-top: 8px; padding-bottom: 8px; } +.active { + background-color: var(--active-drawer-item); + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + .threadListContainer { display: flex; flex-direction: column; } .titleWrapper { overflow: hidden; width: 100%; } .title { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; color: var(--drawer-item-color); line-height: 24px; } .titleLevel0 { font-size: var(--l-font-18); font-weight: var(--semi-bold); } .titleLevel1, .titleLevel2 { font-size: var(--m-font-16); font-weight: var(--semi-bold); } .buttonContainer { width: 24px; align-items: center; justify-content: center; display: flex; } .communityBase { padding: 2px; padding-right: 4px; overflow: hidden; } .communityExpanded { background-color: var(--drawer-open-community-bg); border-top-right-radius: 8px; border-bottom-right-radius: 8px; + padding-top: 4px; + padding-bottom: 4px; } .subchannelsButton { margin-bottom: 6px; margin-top: 4px; display: flex; align-items: center; } diff --git a/web/sidebar/community-drawer-item.react.js b/web/sidebar/community-drawer-item.react.js index 489fffcb2..1a30c5b6a 100644 --- a/web/sidebar/community-drawer-item.react.js +++ b/web/sidebar/community-drawer-item.react.js @@ -1,159 +1,163 @@ // @flow import classnames from 'classnames'; import * as React from 'react'; import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; import { getCommunityDrawerItemHandler } from './community-drawer-item-handlers.react.js'; import css from './community-drawer-item.css'; import { ExpandButton } from './expand-buttons.react.js'; import SubchannelsButton from './subchannels-button.react.js'; import { useSelector } from '../redux/redux-utils.js'; export type DrawerItemProps = { +itemData: CommunityDrawerItemData, +toggleExpanded?: (threadID: string) => void, +expanded: boolean, +paddingLeft: number, +expandable?: boolean, }; const indentation = 14; const subchannelsButtonIndentation = 24; function CommunityDrawerItem(props: DrawerItemProps): React.Node { const { itemData: { threadInfo, itemChildren, hasSubchannelsButton, labelStyle }, expanded, toggleExpanded, paddingLeft, expandable = true, } = props; const children = React.useMemo(() => { if (!expanded) { return null; } if (hasSubchannelsButton) { const buttonPaddingLeft = paddingLeft + subchannelsButtonIndentation; return (
); } if (!itemChildren) { return null; } return itemChildren.map(item => ( )); }, [ expanded, hasSubchannelsButton, itemChildren, paddingLeft, expandable, threadInfo, ]); const onExpandToggled = React.useCallback( () => (toggleExpanded ? toggleExpanded(threadInfo.id) : null), [toggleExpanded, threadInfo.id], ); const itemExpandButton = React.useMemo(() => { if (!expandable) { return null; } if (itemChildren?.length === 0 && !hasSubchannelsButton) { return (
); } return (
); }, [ expandable, itemChildren?.length, hasSubchannelsButton, onExpandToggled, expanded, ]); const Handler = useSelector(state => getCommunityDrawerItemHandler(state.navInfo.tab), ); const [handler, setHandler] = React.useState({ // eslint-disable-next-line no-unused-vars onClick: event => {}, }); const { uiName } = useResolvedThreadInfo(threadInfo); const titleLabel = classnames(css.title, css[labelStyle]); const style = React.useMemo(() => ({ paddingLeft }), [paddingLeft]); + const threadEntry = classnames({ + [css.threadEntry]: true, + [css.active]: handler.isActive, + }); return ( <> -
+
{itemExpandButton}
{uiName}
{children}
); } export type CommunityDrawerItemChatProps = { +itemData: CommunityDrawerItemData, +paddingLeft: number, +expandable?: boolean, }; function CommunityDrawerItemChat( props: CommunityDrawerItemChatProps, ): React.Node { const [expanded, setExpanded] = React.useState(false); const toggleExpanded = React.useCallback(() => { setExpanded(isExpanded => !isExpanded); }, []); return ( ); } const MemoizedCommunityDrawerItemChat: React.ComponentType = React.memo( CommunityDrawerItemChat, ); const MemoizedCommunityDrawerItem: React.ComponentType = React.memo( CommunityDrawerItem, ); export default MemoizedCommunityDrawerItem; diff --git a/web/theme.css b/web/theme.css index 2e6e5da3a..269245907 100644 --- a/web/theme.css +++ b/web/theme.css @@ -1,202 +1,203 @@ :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; --logo-bg: #111827; --spoiler-color: #33332c; --loading-foreground: #1b0e38; --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-filled: var(--violet-dark-100); --btn-bg-outline: var(--shades-black-90); --btn-bg-success: var(--success-dark-50); --btn-bg-danger: var(--error-primary); --btn-bg-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-80); --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-outline-border: var(--shades-black-60); --thread-color-read: var(--shades-black-60); --thread-preview-secondary: var(--shades-black-70); --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); --message-action-tooltip-bg-light: var(--shades-black-80); --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); --chat-message-list-active-border: #5989d6; --sidebars-modal-color: var(--shades-black-60); --sidebars-modal-color-hover: var(--shades-white-100); --inline-engagement-bg: var(--shades-black-70); --inline-engagement-bg-hover: var(--shades-black-80); --inline-engagement-color: var(--fg); --compose-subchannel-header-fg: var(--shades-black-60); --compose-subchannel-header-bg: var(--shades-black-80); --compose-subchannel-label-color: var(--shades-black-60); --compose-subchannel-mark-color: var(--violet-light-100); --enum-option-icon-color: var(--violet-dark-100); --show-password-bg-hover: var(--shades-black-70); --typeahead-overlay-light: var(--shades-black-80); --typeahead-overlay-dark: var(--shades-black-90); --typeahead-overlay-text: var(--shades-white-100); --typeahead-overlay-shadow-primary: rgba(0, 0, 0, 0.25); --typeahead-overlay-shadow-secondary: rgba(0, 0, 0, 0.4); --spoiler-text-color: var(--spoiler-color); --spoiler-background-color: var(--spoiler-color); --purple-link: var(--violet-light-100); --drawer-expand-button: var(--shades-black-60); --drawer-expand-button-disabled: var(--shades-black-80); --drawer-item-color: var(--shades-white-60); --drawer-open-community-bg: #191919; --drawer-bg: var(--shades-black-90); + --active-drawer-item: rgba(0, 0, 0, 0.5); }