diff --git a/client/layout/global-sidebar/footer.tsx b/client/layout/global-sidebar/footer.tsx index 57757c272eecba..b21a2aeeaa837f 100644 --- a/client/layout/global-sidebar/footer.tsx +++ b/client/layout/global-sidebar/footer.tsx @@ -1,4 +1,5 @@ import { recordTracksEvent } from '@automattic/calypso-analytics'; +import { useHasEnTranslation } from '@automattic/i18n-utils'; import { LocalizeProps } from 'i18n-calypso'; import { FC } from 'react'; import AsyncLoad from 'calypso/components/async-load'; @@ -9,27 +10,33 @@ import { UserData } from 'calypso/lib/user/user'; import { useSelector } from 'calypso/state'; import { isSupportSession } from 'calypso/state/support/selectors'; import { GLOBAL_SIDEBAR_EVENTS } from './events'; +import SidebarMenuItem from './menu-items/menu-item'; +import SidebarNotifications from './menu-items/notifications'; +import { SidebarSearch } from './menu-items/search'; export const GlobalSidebarFooter: FC< { translate: LocalizeProps[ 'translate' ]; user?: UserData; } > = ( { translate, user } ) => { + const hasEnTranslation = useHasEnTranslation(); const isInSupportSession = Boolean( useSelector( isSupportSession ) ); + + const isMac = window?.navigator.userAgent && window.navigator.userAgent.indexOf( 'Mac' ) > -1; + const searchShortcut = isMac ? '⌘ + K' : 'Ctrl + K'; + return ( - recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.PROFILE_CLICK ) } - > - - + icon={ } + /> @@ -37,6 +44,20 @@ export const GlobalSidebarFooter: FC< { } onClick={ () => recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.HELPCENTER_CLICK ) } /> + recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.SEARCH_CLICK ) } + /> + recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.NOTIFICATION_CLICK ) } + /> { isInSupportSession && ( ) } diff --git a/client/layout/global-sidebar/header.tsx b/client/layout/global-sidebar/header.tsx index b7e38cef7c642d..f1fe7ec4be2f27 100644 --- a/client/layout/global-sidebar/header.tsx +++ b/client/layout/global-sidebar/header.tsx @@ -1,20 +1,14 @@ import { recordTracksEvent } from '@automattic/calypso-analytics'; -import { useHasEnTranslation } from '@automattic/i18n-utils'; import { useTranslate } from 'i18n-calypso'; import { useSelector } from 'react-redux'; import { getSectionName } from 'calypso/state/ui/selectors'; import SkipNavigation from '../sidebar/skip-navigation'; import { GLOBAL_SIDEBAR_EVENTS } from './events'; -import SidebarNotifications from './menu-items/notifications'; -import { SidebarSearch } from './menu-items/search'; +import SidebarMenuItem from './menu-items/menu-item'; export const GlobalSidebarHeader = () => { - const hasEnTranslation = useHasEnTranslation(); const translate = useTranslate(); - const isMac = window?.navigator.userAgent && window.navigator.userAgent.indexOf( 'Mac' ) > -1; - const searchShortcut = isMac ? '⌘ + K' : 'Ctrl + K'; - const sectionName = useSelector( getSectionName ); return ( @@ -26,30 +20,15 @@ export const GlobalSidebarHeader = () => { { sectionName === 'sites-dashboard' ? ( ) : ( - recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.ALLSITES_CLICK ) } - > - - + icon={ } + /> ) } - - recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.SEARCH_CLICK ) } - /> - recordTracksEvent( GLOBAL_SIDEBAR_EVENTS.NOTIFICATION_CLICK ) } - /> ); }; diff --git a/client/layout/global-sidebar/menu-items/help-center/help-center.jsx b/client/layout/global-sidebar/menu-items/help-center/help-center.jsx index e7f647b23696f6..c541ba5e00f523 100644 --- a/client/layout/global-sidebar/menu-items/help-center/help-center.jsx +++ b/client/layout/global-sidebar/menu-items/help-center/help-center.jsx @@ -9,7 +9,7 @@ import SidebarMenuItem from '../menu-item'; const HELP_CENTER_STORE = HelpCenter.register(); -const SidebarHelpCenter = ( { tooltip, tooltipPlacement, onClick } ) => { +const SidebarHelpCenter = ( { tooltip, onClick } ) => { const helpCenterVisible = useDateStoreSelect( ( select ) => select( HELP_CENTER_STORE ).isHelpCenterShown(), [] @@ -29,7 +29,7 @@ const SidebarHelpCenter = ( { tooltip, tooltipPlacement, onClick } ) => { 'is-active': helpCenterVisible, } ) } tooltip={ tooltip } - tooltipPlacement={ tooltipPlacement } + tooltipPlacement="top" icon={ } /> diff --git a/client/layout/global-sidebar/menu-items/menu-item.jsx b/client/layout/global-sidebar/menu-items/menu-item.jsx deleted file mode 100644 index 8c765ba4d7c985..00000000000000 --- a/client/layout/global-sidebar/menu-items/menu-item.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import { Gridicon } from '@automattic/components'; -import classNames from 'classnames'; -import React, { useRef, forwardRef, Fragment } from 'react'; - -const SidebarMenuItem = forwardRef( - ( - { - url, - tipTarget, - onClick, - tooltip, - tooltipPlacement, - icon, - className, - isActive, - preloadSection, - hasUnseen, - children, - alwaysShowContent, - disabled, - }, - ref - ) => { - const preloadedRef = useRef( false ); - - const preload = () => { - if ( ! preloadedRef.current && preloadSection ) { - preloadedRef.current = true; - preloadSection(); - } - }; - - const renderChildren = () => { - return ( - - { icon && ( typeof icon !== 'string' ? icon : ) } - { children && { children } } - - ); - }; - - const itemClasses = classNames( 'sidebar__item', className, { - 'is-active': isActive, - 'has-unseen': hasUnseen, - 'sidebar__item--always-show-content': alwaysShowContent, - [ `tooltip tooltip-${ tooltipPlacement || 'bottom' }` ]: tooltip, - } ); - - const attributes = { - 'data-tooltip': tooltip, - 'data-tip-target': tipTarget, - onClick: onClick, - className: itemClasses, - onTouchStart: preload, - onMouseEnter: preload, - disabled: disabled, - }; - - return url ? ( - - { renderChildren() } - - ) : ( - - ); - } -); - -export default SidebarMenuItem; diff --git a/client/layout/global-sidebar/menu-items/menu-item.tsx b/client/layout/global-sidebar/menu-items/menu-item.tsx new file mode 100644 index 00000000000000..a73dd60ef571de --- /dev/null +++ b/client/layout/global-sidebar/menu-items/menu-item.tsx @@ -0,0 +1,97 @@ +import classNames from 'classnames'; +import React, { useRef, forwardRef, Fragment } from 'react'; +import { useSelector } from 'react-redux'; +import { useCurrentRoute } from 'calypso/components/route'; +import { getShouldShowGlobalSiteSidebar } from 'calypso/state/global-sidebar/selectors'; +import { getSelectedSiteId } from 'calypso/state/ui/selectors'; +import type { ReactNode, LegacyRef } from 'react'; + +interface Props { + url?: string; + tipTarget?: string; + onClick: () => void; + tooltip: string; + tooltipPlacement: 'bottom' | 'top' | 'right'; + icon?: ReactNode; + className: string; + isActive?: boolean; + preloadSection?: () => void; + hasUnseen?: boolean; + alwaysShowContent?: boolean; + disabled?: boolean; +} + +const SidebarMenuItem = forwardRef< HTMLButtonElement | HTMLAnchorElement, Props >( + ( + { + url, + tipTarget, + onClick, + tooltip, + tooltipPlacement = 'bottom', + icon, + className, + isActive, + preloadSection, + hasUnseen, + alwaysShowContent, + disabled, + }, + ref + ) => { + const preloadedRef = useRef( false ); + + const selectedSiteId = useSelector( getSelectedSiteId ); + const { currentSection } = useCurrentRoute() as { + currentSection: false | { group?: string; name?: string }; + }; + const isSidebarCollapsed = useSelector( ( state ) => { + return getShouldShowGlobalSiteSidebar( + state, + selectedSiteId, + currentSection !== false ? currentSection?.group ?? '' : '', + currentSection !== false ? currentSection?.name ?? '' : '' + ); + } ); + + const preload = () => { + if ( ! preloadedRef.current && preloadSection ) { + preloadedRef.current = true; + preloadSection(); + } + }; + + const renderChildren = () => { + return { icon && <>{ icon } }; + }; + + const itemClasses = classNames( 'sidebar__item', className, { + 'is-active': isActive, + 'has-unseen': hasUnseen, + 'sidebar__item--always-show-content': alwaysShowContent, + [ `tooltip tooltip-${ isSidebarCollapsed ? 'right' : tooltipPlacement }` ]: tooltip, + } ); + + const attributes = { + 'data-tooltip': tooltip, + 'data-tip-target': tipTarget, + onClick: onClick, + className: itemClasses, + onTouchStart: preload, + onMouseEnter: preload, + disabled: disabled, + }; + + return url ? ( + }> + { renderChildren() } + + ) : ( + + ); + } +); + +export default SidebarMenuItem; diff --git a/client/layout/global-sidebar/menu-items/notifications/index.jsx b/client/layout/global-sidebar/menu-items/notifications/index.jsx index 2962c37aa1909d..4c085128d57231 100644 --- a/client/layout/global-sidebar/menu-items/notifications/index.jsx +++ b/client/layout/global-sidebar/menu-items/notifications/index.jsx @@ -9,11 +9,9 @@ import { withCurrentRoute } from 'calypso/components/route'; import TranslatableString from 'calypso/components/translatable/proptype'; import SidebarMenuItem from 'calypso/layout/global-sidebar/menu-items/menu-item'; import { recordTracksEvent } from 'calypso/state/analytics/actions'; -import { getShouldShowGlobalSiteSidebar } from 'calypso/state/global-sidebar/selectors'; import hasUnseenNotifications from 'calypso/state/selectors/has-unseen-notifications'; import isNotificationsOpen from 'calypso/state/selectors/is-notifications-open'; import { toggleNotificationsPanel } from 'calypso/state/ui/actions'; -import { getSelectedSiteId } from 'calypso/state/ui/selectors'; import { BellIcon } from './icon'; import './style.scss'; @@ -28,7 +26,6 @@ class SidebarNotifications extends Component { isNotificationsOpen: PropTypes.bool, hasUnseenNotifications: PropTypes.bool, tooltip: TranslatableString, - shouldShowGlobalSiteSidebar: PropTypes.bool, }; notificationLink = createRef(); @@ -146,10 +143,10 @@ class SidebarNotifications extends Component { onClick={ this.handleClick } isActive={ this.props.isActive } tooltip={ this.props.tooltip } + tooltipPlacement="top" className={ classes } ref={ this.notificationLink } key={ this.state.animationState } - tooltipPlacement={ this.props.shouldShowGlobalSiteSidebar ? 'bottom-left' : 'bottom' } />
{ - const sectionGroup = currentSection?.group ?? null; - const sectionName = currentSection?.name ?? null; - const siteId = getSelectedSiteId( state ); - const shouldShowGlobalSiteSidebar = getShouldShowGlobalSiteSidebar( - state, - siteId, - sectionGroup, - sectionName - ); +const mapStateToProps = ( state ) => { return { isNotificationsOpen: isNotificationsOpen( state ), hasUnseenNotifications: hasUnseenNotifications( state ), - shouldShowGlobalSiteSidebar, }; }; const mapDispatchToProps = { diff --git a/client/layout/global-sidebar/menu-items/search/index.jsx b/client/layout/global-sidebar/menu-items/search/index.jsx index 7f9843fe266074..caa5fb36ceea9e 100644 --- a/client/layout/global-sidebar/menu-items/search/index.jsx +++ b/client/layout/global-sidebar/menu-items/search/index.jsx @@ -1,11 +1,7 @@ import { Icon, search } from '@wordpress/icons'; import classnames from 'classnames'; -import { useSelector } from 'react-redux'; -import { useCurrentRoute } from 'calypso/components/route'; import { useDispatch } from 'calypso/state'; import { openCommandPalette } from 'calypso/state/command-palette/actions'; -import { getShouldShowGlobalSiteSidebar } from 'calypso/state/global-sidebar/selectors'; -import { getSelectedSiteId } from 'calypso/state/ui/selectors'; import SidebarMenuItem from '../menu-item'; export const SidebarSearch = ( { tooltip, onClick } ) => { @@ -14,16 +10,6 @@ export const SidebarSearch = ( { tooltip, onClick } ) => { dispatch( openCommandPalette() ); onClick(); }; - const selectedSiteId = useSelector( getSelectedSiteId ); - const { currentSection } = useCurrentRoute(); - const shouldShowGlobalSiteSidebar = useSelector( ( state ) => { - return getShouldShowGlobalSiteSidebar( - state, - selectedSiteId, - currentSection?.group, - currentSection?.name - ); - } ); return ( <> { 'is-active': false, } ) } tooltip={ tooltip } + tooltipPlacement="top" icon={ } - tooltipPlacement={ shouldShowGlobalSiteSidebar ? 'bottom-left' : 'bottom' } /> ); diff --git a/client/layout/global-sidebar/style.scss b/client/layout/global-sidebar/style.scss index 705ab2bd0a1647..7f6e6388a282f2 100644 --- a/client/layout/global-sidebar/style.scss +++ b/client/layout/global-sidebar/style.scss @@ -25,7 +25,6 @@ $brand-text: "SF Pro Text", $sans; line-height: 20px; background: var(--color-sidebar-tooltip-background); border-radius: 4px; - bottom: -24px; color: var(--color-sidebar-tooltip-text); content: attr(data-tooltip); display: none; @@ -33,7 +32,6 @@ $brand-text: "SF Pro Text", $sans; opacity: 0.95; padding: 3px 6px; position: absolute; - right: 0; white-space: nowrap; z-index: 8; } @@ -43,20 +41,26 @@ $brand-text: "SF Pro Text", $sans; } } - .tooltip-bottom-left { - &::after { - left: 0; - right: unset; - } + .tooltip-bottom::after { + bottom: -24px; + left: 50%; + transform: translateX(-50%); } - .tooltip-top { - &::after { - right: unset; - bottom: unset; - left: 0; - top: -29px; - } + .tooltip-top::after { + top: -29px; + left: 50%; + transform: translateX(-50%); + } + + .tooltip-right::after { + top: 50%; + transform: translateY(-50%); + left: calc(100% + 8px); + } + + .sidebar__body .tooltip-right::after { + left: 90%; } .sidebar__item { @@ -75,24 +79,14 @@ $brand-text: "SF Pro Text", $sans; text-decoration: none; } - span.dotcom, - button.sidebar__item-search, - a.sidebar__item-notifications { + span.dotcom { display: flex; - width: 28px; + width: 125px; height: 28px; margin: 0; - } - - span.gap { - flex: 1; - } - - span.dotcom { background-image: url(calypso/assets/images/global-sidebar/dotcom.svg); background-repeat: no-repeat; background-position: center; - width: 125px; } .link-logo { @@ -200,7 +194,7 @@ $brand-text: "SF Pro Text", $sans; display: flex; gap: 8px; align-items: center; - padding: 16px 24px 16px 24px; + padding: 16px 24px; .sidebar__menu-icon { margin-right: 0; @@ -210,7 +204,9 @@ $brand-text: "SF Pro Text", $sans; align-items: center; border-radius: 2px; } - .sidebar__item-help { + .sidebar__item-help, + .sidebar__item-notifications, + .sidebar__item-search { display: flex; align-items: center; padding: 4px; @@ -284,7 +280,9 @@ $brand-text: "SF Pro Text", $sans; .sidebar__footer-language-switcher, .sidebar__footer-link, - .sidebar__item-help { + .sidebar__item-help, + .sidebar__item-notifications, + .sidebar__item-search { &:hover { background-color: var(--color-sidebar-menu-hover-background); border-radius: 4px; @@ -426,10 +424,6 @@ $brand-text: "SF Pro Text", $sans; .sidebar__header, .sidebar__footer { flex-direction: column; - - .sidebar__footer-profile { - padding: 0; - } } .sidebar__header { @@ -446,6 +440,7 @@ $brand-text: "SF Pro Text", $sans; } .sidebar__body { + overflow-y: visible; .sidebar__menu-item-parent .sidebar__menu-link { margin: 0 auto; diff --git a/client/layout/sidebar/item.jsx b/client/layout/sidebar/item.jsx index f712321cab094b..ba532a68899b96 100644 --- a/client/layout/sidebar/item.jsx +++ b/client/layout/sidebar/item.jsx @@ -15,7 +15,7 @@ export default function SidebarItem( props ) { const classes = classnames( props.className, props.tipTarget, { selected: props.selected, 'has-unseen': props.hasUnseen, - tooltip: !! props.tooltip, + 'tooltip tooltip-right': !! props.tooltip, } ); const sidebarIsCollapsed = useSelector( getSidebarIsCollapsed ); const { materialIcon, materialIconStyle, icon, customIcon, count, badge } = props; diff --git a/client/sites-dashboard-v2/dotcom-style.scss b/client/sites-dashboard-v2/dotcom-style.scss index 8f937ecfba0592..69991f4d7ac792 100644 --- a/client/sites-dashboard-v2/dotcom-style.scss +++ b/client/sites-dashboard-v2/dotcom-style.scss @@ -262,7 +262,6 @@ } } .sidebar__body { - padding-top: 24px; .sidebar__menu-link-text { transition: all 100ms ease-out; transition-delay: 120ms; @@ -282,9 +281,9 @@ } .sidebar__footer { flex-direction: row !important; - .sidebar__item-help { - padding-inline: 0; - } + padding: 16px; + align-items: center; + justify-content: center; } } } diff --git a/client/state/global-sidebar/selectors.ts b/client/state/global-sidebar/selectors.ts index 45494c4aaaa2b0..1d63bdaac807f5 100644 --- a/client/state/global-sidebar/selectors.ts +++ b/client/state/global-sidebar/selectors.ts @@ -13,7 +13,7 @@ const GLOBAL_SITE_VIEW_SECTION_NAMES: string[] = [ 'site-monitoring', ]; -function shouldShowGlobalSiteViewSection( siteId: number, sectionName: string ) { +function shouldShowGlobalSiteViewSection( siteId: number | null, sectionName: string ) { return ( isEnabled( 'layout/dotcom-nav-redesign-v2' ) && !! siteId && @@ -23,7 +23,7 @@ function shouldShowGlobalSiteViewSection( siteId: number, sectionName: string ) export const getShouldShowGlobalSiteSidebar = ( state: AppState, - siteId: number, + siteId: number | null, sectionGroup: string, sectionName: string ) => {