From f972084c65c6252e3cfb978a77ebcabc9c8e8f63 Mon Sep 17 00:00:00 2001 From: Jackie Chan Date: Thu, 20 Nov 2025 00:37:02 -0800 Subject: [PATCH 01/14] feat(preview-modernization): Update icons in sidebar nav --- .../SidebarToggleButton.js | 21 ++++- src/elements/content-sidebar/SidebarNav.js | 76 ++++++++++++++++--- .../content-sidebar/SidebarNavButton.js | 67 +++++++++++----- .../content-sidebar/SidebarNavSignButton.tsx | 58 +++++++++++--- src/elements/content-sidebar/_mixins.scss | 7 +- .../additional-tabs/AdditionalTabTooltip.js | 13 ++++ .../additional-tabs/AdditionalTabs.js | 10 ++- .../additional-tabs/AdditionalTabs.scss | 9 +++ 8 files changed, 216 insertions(+), 45 deletions(-) diff --git a/src/components/sidebar-toggle-button/SidebarToggleButton.js b/src/components/sidebar-toggle-button/SidebarToggleButton.js index 3564febd1f..2d66846097 100644 --- a/src/components/sidebar-toggle-button/SidebarToggleButton.js +++ b/src/components/sidebar-toggle-button/SidebarToggleButton.js @@ -3,12 +3,12 @@ import * as React from 'react'; import classNames from 'classnames'; import { injectIntl } from 'react-intl'; import type { IntlShape } from 'react-intl'; - +import { Tooltip as BPTooltip } from '@box/blueprint-web'; import IconHide from '../../icons/general/IconHide'; import IconShow from '../../icons/general/IconShow'; import PlainButton from '../plain-button'; import Tooltip from '../tooltip'; - +import { useFeatureConfig } from '../../elements/common/feature-checking'; import messages from '../../elements/common/messages'; import './SidebarToggleButton.scss'; @@ -32,14 +32,15 @@ const SidebarToggleButton = ({ onClick, ...rest }: Props) => { + const { enabled: isPreviewModernizationEnabled } = useFeatureConfig('previewModernization'); const isCollapsed = !isOpen ? 'collapsed' : ''; const intlMessage = isOpen ? messages.sidebarHide : messages.sidebarShow; const intlText = intl.formatMessage(intlMessage); const classes = classNames(className, 'bdl-SidebarToggleButton', { 'bdl-is-collapsed': isCollapsed, + 'bdl-SidebarToggleButton--modernized': isPreviewModernizationEnabled, }); const tooltipPosition = direction === DIRECTION_LEFT ? 'middle-right' : 'middle-left'; - const renderButton = () => { if (direction === DIRECTION_LEFT) { return isOpen ? : ; @@ -47,6 +48,20 @@ const SidebarToggleButton = ({ return isOpen ? : ; }; + if (isPreviewModernizationEnabled) { + const tooltipPositionModernized = direction === DIRECTION_LEFT ? DIRECTION_RIGHT : DIRECTION_LEFT; + + return ( + + {/* Workaround to attach BP tooltip to legacy button, remove span when buttons are migrated to BP */} + + + {renderButton()} + + + + ); + } return ( diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index d92cee1eba..492d45db75 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -9,11 +9,16 @@ import { injectIntl } from 'react-intl'; import type { IntlShape } from 'react-intl'; import classNames from 'classnames'; import noop from 'lodash/noop'; -// $FlowFixMe -import { BoxAiLogo } from '@box/blueprint-web-assets/icons/Logo'; -// $FlowFixMe -import { Size6 } from '@box/blueprint-web-assets/tokens/tokens'; +import classNames from 'classnames'; +import { BoxAiLogo, BoxAiLogo24 } from '@box/blueprint-web-assets/icons/Logo'; +import { Size6, Size5, IconIconBlue } from '@box/blueprint-web-assets/tokens/tokens'; import { usePromptFocus } from '@box/box-ai-content-answers'; +import CommentIcon from '@box/blueprint-web-assets/icons/Medium/Comment'; +import CommentIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/Comment'; +import InfoIcon from '@box/blueprint-web-assets/icons/Medium/InformationCircle'; +import InfoIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/InformationCircle'; +import MetadataIcon from '@box/blueprint-web-assets/icons/Medium/Metadata'; +import MetadataIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/Metadata'; import AdditionalTabs from './additional-tabs'; import DocGenIcon from '../../icon/fill/DocGenIcon'; import IconChatRound from '../../icons/general/IconChatRound'; @@ -40,6 +45,11 @@ import type { InternalSidebarNavigation, InternalSidebarNavigationHandler } from import './SidebarNav.scss'; import type { SignSidebarProps } from './SidebarNavSign'; +const SIDEBAR_TAB_ICON_PROPS = { + height: Size5, + width: Size5, +}; + type Props = { additionalTabs?: Array, elementId: string, @@ -97,6 +107,40 @@ const SidebarNav = ({ } }; + // Icon wrapper components that receive isActive prop from SidebarNavButton + const ActivityIconWrapper = ({ isActive }: { isActive?: boolean }) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); + }; + + const DetailsIconWrapper = ({ isActive }: { isActive?: boolean }) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); + }; + + const MetadataIconWrapper = ({ isActive }: { isActive?: boolean }) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); + }; + return (
@@ -110,6 +154,7 @@ const SidebarNav = ({ > {hasBoxAI && ( - + {isPreviewModernizationEnabled ? ( + + ) : ( + + )} )} {hasActivity && ( - + )} {hasDetails && ( - + )} {hasSkills && ( - + )} {hasDocGen && ( - +
)}
diff --git a/src/elements/content-sidebar/SidebarNavButton.js b/src/elements/content-sidebar/SidebarNavButton.js index 15fcae0de9..64669866f7 100644 --- a/src/elements/content-sidebar/SidebarNavButton.js +++ b/src/elements/content-sidebar/SidebarNavButton.js @@ -8,10 +8,14 @@ import * as React from 'react'; import { Route } from 'react-router-dom'; import noop from 'lodash/noop'; import classNames from 'classnames'; -import { Button } from '@box/blueprint-web'; +import { Button, Tooltip as BPTooltip } from '@box/blueprint-web'; import Tooltip from '../../components/tooltip/Tooltip'; import { isLeftClick } from '../../utils/dom'; -import type { InternalSidebarNavigation, InternalSidebarNavigationHandler, ViewTypeValues } from '../common/types/SidebarNavigation'; +import type { + InternalSidebarNavigation, + InternalSidebarNavigationHandler, + ViewTypeValues, +} from '../common/types/SidebarNavigation'; import './SidebarNavButton.scss'; type Props = { @@ -27,6 +31,7 @@ type Props = { routerDisabled?: boolean, sidebarView: ViewTypeValues, tooltip: React.Node, + isPreviewModernizationEnabled?: boolean, }; const SidebarNavButton = React.forwardRef>((props: Props, ref: React.Ref) => { @@ -43,39 +48,54 @@ const SidebarNavButton = React.forwardRef>((props: Props, routerDisabled = false, sidebarView, tooltip, + isPreviewModernizationEnabled = false, } = props; const sidebarPath = `/${sidebarView}`; const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`; + const TooltipComponent = isPreviewModernizationEnabled ? BPTooltip : Tooltip; + // Blueprint Tooltip uses 'content' prop, legacy Tooltip uses 'text' prop + const tooltipProps = isPreviewModernizationEnabled + ? { content: tooltip, side: 'left' } + : { text: tooltip, position: 'middle-left', isTabbable: false }; + if (routerDisabled) { // Mimic router behavior using internalSidebarNavigation const isMatch = !!internalSidebarNavigation && internalSidebarNavigation.sidebar === sidebarView; const isActiveValue = isMatch && !!isOpen; - + // Mimic isExactMatch: true when no extra navigation parameters are present - const hasExtraParams = internalSidebarNavigation && ( - internalSidebarNavigation.versionId || - internalSidebarNavigation.activeFeedEntryType || - internalSidebarNavigation.activeFeedEntryId || - internalSidebarNavigation.fileVersionId - ); + const hasExtraParams = + internalSidebarNavigation && + (internalSidebarNavigation.versionId || + internalSidebarNavigation.activeFeedEntryType || + internalSidebarNavigation.activeFeedEntryId || + internalSidebarNavigation.fileVersionId); const isExactMatch = isMatch && !hasExtraParams; - + const handleNavButtonClick = event => { onClick(sidebarView); - + // Mimic router navigation behavior if (internalSidebarNavigationHandler && !event.defaultPrevented && isLeftClick(event)) { const replace = isExactMatch; - internalSidebarNavigationHandler({ - sidebar: sidebarView, - open: true, - }, replace); + internalSidebarNavigationHandler( + { + sidebar: sidebarView, + open: true, + }, + replace, + ); } }; + // Clone children and pass isActive prop + const childrenWithProps = React.isValidElement(children) + ? React.cloneElement(children, { isActive: isActiveValue }) + : children; + return ( - + - + ); } @@ -121,8 +141,13 @@ const SidebarNavButton = React.forwardRef>((props: Props, } }; + // Clone children and pass isActive prop + const childrenWithProps = React.isValidElement(children) + ? React.cloneElement(children, { isActive: isActiveValue }) + : children; + return ( - + - + ); }} diff --git a/src/elements/content-sidebar/SidebarNavSignButton.tsx b/src/elements/content-sidebar/SidebarNavSignButton.tsx index 33a43356b0..9e9f83974a 100644 --- a/src/elements/content-sidebar/SidebarNavSignButton.tsx +++ b/src/elements/content-sidebar/SidebarNavSignButton.tsx @@ -1,12 +1,16 @@ import * as React from 'react'; import classnames from 'classnames'; import { injectIntl, IntlShape } from 'react-intl'; +import SignIcon from '@box/blueprint-web-assets/icons/Medium/Sign'; +import { IconIconBlue, Size5 } from '@box/blueprint-web-assets/tokens/tokens'; +import { Tooltip as BPTooltip } from '@box/blueprint-web'; import BoxSign28 from '../../icon/logo/BoxSign28'; import Sign16 from '../../icon/fill/Sign16'; import PlainButton, { PlainButtonProps } from '../../components/plain-button'; // @ts-ignore Module is written in Flow import TargetedClickThroughGuideTooltip from '../../features/targeting/TargetedClickThroughGuideTooltip'; import Tooltip, { TooltipPosition } from '../../components/tooltip'; +import { useFeatureConfig } from '../common/feature-checking'; // @ts-ignore Module is written in Flow import messages from './messages'; import './SidebarNavSignButton.scss'; @@ -30,6 +34,7 @@ export function SidebarNavSignButton({ blockedReason, intl, targetingApi, ...res const FtuxTooltip = !isSignDisabled && isTargeted ? TargetedClickThroughGuideTooltip : PlaceholderTooltip; const label = intl.formatMessage(messages.boxSignRequest); const buttonClassName = classnames('bcs-SidebarNavSignButton', { 'bdl-is-disabled': isSignDisabled }); + const { enabled: isPreviewModernizationEnabled } = useFeatureConfig('previewModernization'); let tooltipMessage = label; @@ -45,15 +50,38 @@ export function SidebarNavSignButton({ blockedReason, intl, targetingApi, ...res default: } - return ( - targetingApi} - > - + const renderButtonWithTooltip = () => { + const isDropdownOpen = rest['aria-expanded'] === 'true'; + + // Use Blueprint tooltip when modernization is enabled + if (isPreviewModernizationEnabled) { + const modernizedButton = ( + + + + ); + + if (isTargeted) { + return modernizedButton; + } + + return ( + + {/* Workaround to attach BP tooltip to legacy button, remove span when buttons are migrated to BP */} + {modernizedButton} + + ); + } + + // Use legacy tooltip by default + return ( + + ); + }; + + return ( + targetingApi} + > + {renderButtonWithTooltip()} ); } diff --git a/src/elements/content-sidebar/_mixins.scss b/src/elements/content-sidebar/_mixins.scss index 646eceb101..84d4c4d67c 100644 --- a/src/elements/content-sidebar/_mixins.scss +++ b/src/elements/content-sidebar/_mixins.scss @@ -14,7 +14,7 @@ } &.bdl-is-disabled { - opacity: .5; + opacity: 0.5; } &.bdl-is-hidden { @@ -27,6 +27,11 @@ height: 24px; } +@mixin bdl-SidebarNavIconModernized { + width: 20px; + height: 20px; +} + @mixin bcs-SidebarSection { margin: 0 8px 20px 25px; diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTabTooltip.js b/src/elements/content-sidebar/additional-tabs/AdditionalTabTooltip.js index 7185ab6899..318dcdc255 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTabTooltip.js +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTabTooltip.js @@ -5,8 +5,10 @@ */ import * as React from 'react'; +import { Tooltip as BPTooltip } from '@box/blueprint-web'; import Tooltip from '../../common/Tooltip'; import TargetedClickThroughGuideTooltip from '../../../features/targeting/TargetedClickThroughGuideTooltip'; +import { useFeatureConfig } from '../../common/feature-checking'; import type { AdditionalSidebarTabFtuxData } from '../flowTypes'; import './AdditionalTabTooltip.scss'; @@ -18,7 +20,18 @@ type Props = { }; const AdditionalTabTooltip = ({ children, defaultTooltipText, isFtuxVisible, ftuxTooltipData }: Props) => { + const { enabled: isPreviewModernizationEnabled } = useFeatureConfig('previewModernization'); + if (!isFtuxVisible || !ftuxTooltipData || !ftuxTooltipData.targetingApi().canShow) { + if (isPreviewModernizationEnabled) { + return ( + + {/* Workaround to attach BP tooltip to legacy button */} + {children} + + ); + } + return ( {children} diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.js b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.js index d4579a05a5..9186dca084 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.js +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.js @@ -5,6 +5,7 @@ */ import React, { PureComponent } from 'react'; +import classNames from 'classnames'; import AdditionalTab from './AdditionalTab'; import AdditionalTabsLoading from './AdditionalTabsLoading'; import type { AdditionalSidebarTab } from '../flowTypes'; @@ -13,6 +14,7 @@ import './AdditionalTabs.scss'; type Props = { tabs?: Array, + isPreviewModernizationEnabled?: boolean, }; type State = { @@ -53,11 +55,15 @@ class AdditionalTabs extends PureComponent { }; render() { - const { tabs } = this.props; + const { tabs, isPreviewModernizationEnabled } = this.props; const { isLoading } = this.state; return ( -
+
{isLoading && } {tabs && tabs.map(tabData => ( diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss index 3ed6a9e01f..85d29cdceb 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss @@ -1,4 +1,13 @@ +@import '../mixins'; + .bdl-AdditionalTabs { display: flex; flex-direction: column; + + &--modernized { + .bdl-AdditionalTab-icon, + .bdl-AdditionalTabPlaceholder-icon { + @include bdl-SidebarNavIconModernized; + } + } } From 0887e11b12cad118c3f956d7b5bb02f5c1c8c602 Mon Sep 17 00:00:00 2001 From: Jackie Chan Date: Thu, 20 Nov 2025 01:15:34 -0800 Subject: [PATCH 02/14] feat(preview-modernization): scale icons on hover --- .../SidebarToggleButton.scss | 13 +++++++++++++ src/elements/content-sidebar/SidebarNav.js | 7 ++++++- .../content-sidebar/SidebarNavButton.scss | 17 ++++++++++++++--- .../content-sidebar/SidebarNavSignButton.scss | 10 +++++++++- .../additional-tabs/AdditionalTab.scss | 11 ++++++++++- 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/components/sidebar-toggle-button/SidebarToggleButton.scss b/src/components/sidebar-toggle-button/SidebarToggleButton.scss index 510da1944b..62b944bf0f 100644 --- a/src/components/sidebar-toggle-button/SidebarToggleButton.scss +++ b/src/components/sidebar-toggle-button/SidebarToggleButton.scss @@ -29,3 +29,16 @@ } } } + +// Modernized hover and collapsed effects with feature flag +.bcs-SidebarNav--modernized { + .bdl-SidebarToggleButton { + &:not(.bdl-is-disabled):hover svg, + &:not(.is-disabled):hover svg, + &.bdl-is-collapsed svg, + &.bdl-is-collapsed:hover svg { + transform: scale(1.09); + transition: transform 150ms; + } + } +} diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index 492d45db75..83a2f783d4 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -142,7 +142,12 @@ const SidebarNav = ({ }; return ( -
+
Date: Thu, 20 Nov 2025 01:21:04 -0800 Subject: [PATCH 03/14] feat(preview-modernization): Add focus selector --- .../sidebar-toggle-button/SidebarToggleButton.scss | 3 ++- src/elements/content-sidebar/SidebarNavButton.scss | 2 +- src/elements/content-sidebar/SidebarNavSignButton.scss | 4 ++-- .../content-sidebar/additional-tabs/AdditionalTab.scss | 5 +++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/sidebar-toggle-button/SidebarToggleButton.scss b/src/components/sidebar-toggle-button/SidebarToggleButton.scss index 62b944bf0f..f62b6a3d1a 100644 --- a/src/components/sidebar-toggle-button/SidebarToggleButton.scss +++ b/src/components/sidebar-toggle-button/SidebarToggleButton.scss @@ -30,11 +30,12 @@ } } -// Modernized hover and collapsed effects with feature flag .bcs-SidebarNav--modernized { .bdl-SidebarToggleButton { &:not(.bdl-is-disabled):hover svg, &:not(.is-disabled):hover svg, + &:not(.bdl-is-disabled):focus svg, + &:not(.is-disabled):focus svg, &.bdl-is-collapsed svg, &.bdl-is-collapsed:hover svg { transform: scale(1.09); diff --git a/src/elements/content-sidebar/SidebarNavButton.scss b/src/elements/content-sidebar/SidebarNavButton.scss index 66304c8789..96437e5f01 100644 --- a/src/elements/content-sidebar/SidebarNavButton.scss +++ b/src/elements/content-sidebar/SidebarNavButton.scss @@ -45,10 +45,10 @@ } } -// Modernized hover and selected effects with feature flag .bcs-SidebarNav--modernized { .bcs-NavButton { &:hover svg, + &:focus svg, &.bcs-is-selected svg { transform: scale(1.09); transition: transform 150ms; diff --git a/src/elements/content-sidebar/SidebarNavSignButton.scss b/src/elements/content-sidebar/SidebarNavSignButton.scss index db8c8e2787..28407764e6 100644 --- a/src/elements/content-sidebar/SidebarNavSignButton.scss +++ b/src/elements/content-sidebar/SidebarNavSignButton.scss @@ -14,9 +14,9 @@ margin-top: 2px; // for visual alignment; } -// Modernized hover effect with feature flag .bcs-SidebarNav--modernized { - .bcs-SidebarNavSignButton:hover svg { + .bcs-SidebarNavSignButton:hover svg, + .bcs-SidebarNavSignButton:focus svg { transform: scale(1.09); transition: transform 150ms; } diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss b/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss index aa98ea96ba..071b90b14a 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss @@ -12,10 +12,11 @@ } } -// Modernized hover effect with feature flag .bcs-SidebarNav--modernized { .bdl-AdditionalTab:hover svg, - .bdl-AdditionalTab:hover img { + .bdl-AdditionalTab:hover img, + .bdl-AdditionalTab:focus svg, + .bdl-AdditionalTab:focus img { transform: scale(1.09); transition: transform 150ms; } From 2b7b9c3f964873c9405b1d7dc973ac2b50660d8c Mon Sep 17 00:00:00 2001 From: Jackie Chan Date: Thu, 20 Nov 2025 11:42:54 -0800 Subject: [PATCH 04/14] feat(preview-modernization): remove hover effect from disabled buttons --- src/elements/content-sidebar/SidebarNavButton.scss | 4 ++-- src/elements/content-sidebar/SidebarNavSignButton.scss | 4 ++-- .../content-sidebar/additional-tabs/AdditionalTab.scss | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/elements/content-sidebar/SidebarNavButton.scss b/src/elements/content-sidebar/SidebarNavButton.scss index 96437e5f01..7ba6e9ebea 100644 --- a/src/elements/content-sidebar/SidebarNavButton.scss +++ b/src/elements/content-sidebar/SidebarNavButton.scss @@ -47,8 +47,8 @@ .bcs-SidebarNav--modernized { .bcs-NavButton { - &:hover svg, - &:focus svg, + &:not([aria-disabled='true']):hover svg, + &:not([aria-disabled='true']):focus svg, &.bcs-is-selected svg { transform: scale(1.09); transition: transform 150ms; diff --git a/src/elements/content-sidebar/SidebarNavSignButton.scss b/src/elements/content-sidebar/SidebarNavSignButton.scss index 28407764e6..91a48e01b4 100644 --- a/src/elements/content-sidebar/SidebarNavSignButton.scss +++ b/src/elements/content-sidebar/SidebarNavSignButton.scss @@ -15,8 +15,8 @@ } .bcs-SidebarNav--modernized { - .bcs-SidebarNavSignButton:hover svg, - .bcs-SidebarNavSignButton:focus svg { + .bcs-SidebarNavSignButton:not(.bdl-is-disabled):hover svg, + .bcs-SidebarNavSignButton:not(.bdl-is-disabled):focus svg { transform: scale(1.09); transition: transform 150ms; } diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss b/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss index 071b90b14a..46b399ec6b 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTab.scss @@ -13,10 +13,10 @@ } .bcs-SidebarNav--modernized { - .bdl-AdditionalTab:hover svg, - .bdl-AdditionalTab:hover img, - .bdl-AdditionalTab:focus svg, - .bdl-AdditionalTab:focus img { + .bdl-AdditionalTab:not(.bdl-is-disabled):hover svg, + .bdl-AdditionalTab:not(.bdl-is-disabled):hover img, + .bdl-AdditionalTab:not(.bdl-is-disabled):focus svg, + .bdl-AdditionalTab:not(.bdl-is-disabled):focus img { transform: scale(1.09); transition: transform 150ms; } From a26a459ef980db9173e71b4d805b772670df3339 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Mon, 1 Dec 2025 16:07:57 -0500 Subject: [PATCH 05/14] feat(preview-modernization): fix flow issues --- src/elements/content-sidebar/SidebarNavButton.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/elements/content-sidebar/SidebarNavButton.js b/src/elements/content-sidebar/SidebarNavButton.js index 64669866f7..f64f5979bb 100644 --- a/src/elements/content-sidebar/SidebarNavButton.js +++ b/src/elements/content-sidebar/SidebarNavButton.js @@ -21,7 +21,7 @@ import './SidebarNavButton.scss'; type Props = { 'data-resin-target'?: string, 'data-testid'?: string, - children: React.Node, + children: React.Element, elementId?: string, internalSidebarNavigation?: InternalSidebarNavigation, internalSidebarNavigationHandler?: InternalSidebarNavigationHandler, @@ -90,9 +90,7 @@ const SidebarNavButton = React.forwardRef>((props: Props, }; // Clone children and pass isActive prop - const childrenWithProps = React.isValidElement(children) - ? React.cloneElement(children, { isActive: isActiveValue }) - : children; + const childrenWithProps = React.cloneElement(children, { isActive: isActiveValue }); return ( @@ -142,9 +140,7 @@ const SidebarNavButton = React.forwardRef>((props: Props, }; // Clone children and pass isActive prop - const childrenWithProps = React.isValidElement(children) - ? React.cloneElement(children, { isActive: isActiveValue }) - : children; + const childrenWithProps = React.cloneElement(children, { isActive: isActiveValue }); return ( From 35a5c4cfa2bc728ee0b31b4a7d93650a08f8914b Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Mon, 1 Dec 2025 16:30:01 -0500 Subject: [PATCH 06/14] feat(preview-modernization): fix tests --- .../__tests__/SidebarNavButton.test.js | 90 ++++++++++--------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js b/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js index 2b25c3c02f..cbfbdfb940 100644 --- a/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js +++ b/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { MemoryRouter, Router } from 'react-router-dom'; -// Using fireEvent for all click interactions instead of userEvent because +// Using fireEvent for all click interactions instead of userEvent because // userEvent.pointer with right-click doesn't reliably trigger onClick handlers import { render, screen, fireEvent } from '../../../test-utils/testing-library'; import SidebarNavButton from '../SidebarNavButton'; @@ -23,7 +23,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { renderWrapper({ tooltip: 'foo', sidebarView: 'activity', - children: 'test button', + children: test button, }); const button = screen.getByRole('tab'); @@ -49,7 +49,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { isOpen, sidebarView: 'activity', tooltip: 'foo', - children: 'test button', + children: test button, }; renderWrapper(props, '/activity'); const button = screen.getByRole('tab'); @@ -78,7 +78,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { isOpen: true, sidebarView: 'activity', tooltip: 'foo', - children: 'test button', + children: test button, }, path, ); @@ -103,7 +103,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { onClick: mockOnClick, sidebarView: mockSidebarView, tooltip: 'test', - children: 'button', + children: button, }); const button = screen.getByText('button'); @@ -117,12 +117,11 @@ describe('elements/content-sidebar/SidebarNavButton', () => { ${false} | ${false} ${undefined} | ${false} `('should apply bdl-is-disabled class when isDisabled is $isDisabled', ({ isDisabled, expected }) => { - const content = 'Activity'; renderWrapper({ isDisabled, sidebarView: 'activity', tooltip: 'Activity', - children: content, + children: Activity, }); const button = screen.getByRole('tab'); @@ -146,7 +145,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { elementId, sidebarView, tooltip: 'test', - children: 'test button', + children: test button, }); const button = screen.getByRole('tab'); @@ -162,7 +161,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { ref, sidebarView: 'activity', tooltip: 'test', - children: 'test button', + children: test button, }); const button = screen.getByRole('tab'); @@ -183,7 +182,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => { return render( - Activity + Activity , ); @@ -267,7 +266,7 @@ describe('elements/content-sidebar/SidebarNavButton - Router Disabled', () => { internalSidebarNavigation: { sidebar: 'skills' }, }; - const renderWithoutRouter = ({ children = 'test button', ref, ...props }) => + const renderWithoutRouter = ({ children = test button, ref, ...props }) => render( {children} @@ -291,29 +290,32 @@ describe('elements/content-sidebar/SidebarNavButton - Router Disabled', () => { }); test.each` - internalSidebarNavigation | expected - ${null} | ${false} - ${undefined} | ${false} - ${{ sidebar: 'skills' }} | ${false} - ${{ sidebar: 'activity' }} | ${true} - ${{ sidebar: 'activity', versionId: '123' }} | ${true} - `('should reflect active state ($expected) correctly based on internal navigation', ({ expected, internalSidebarNavigation }) => { - renderWithoutRouter({ - internalSidebarNavigation, - isOpen: true, - }); - const button = screen.getByRole('tab'); + internalSidebarNavigation | expected + ${null} | ${false} + ${undefined} | ${false} + ${{ sidebar: 'skills' }} | ${false} + ${{ sidebar: 'activity' }} | ${true} + ${{ sidebar: 'activity', versionId: '123' }} | ${true} + `( + 'should reflect active state ($expected) correctly based on internal navigation', + ({ expected, internalSidebarNavigation }) => { + renderWithoutRouter({ + internalSidebarNavigation, + isOpen: true, + }); + const button = screen.getByRole('tab'); - if (expected) { - expect(button).toHaveClass('bcs-is-selected'); - expect(button).toHaveAttribute('aria-selected', 'true'); - expect(button).toHaveAttribute('tabindex', '0'); - } else { - expect(button).not.toHaveClass('bcs-is-selected'); - expect(button).toHaveAttribute('aria-selected', 'false'); - expect(button).toHaveAttribute('tabindex', '-1'); - } - }); + if (expected) { + expect(button).toHaveClass('bcs-is-selected'); + expect(button).toHaveAttribute('aria-selected', 'true'); + expect(button).toHaveAttribute('tabindex', '0'); + } else { + expect(button).not.toHaveClass('bcs-is-selected'); + expect(button).toHaveAttribute('aria-selected', 'false'); + expect(button).toHaveAttribute('tabindex', '-1'); + } + }, + ); test('should call onClick with sidebarView when clicked', () => { const mockOnClick = jest.fn(); @@ -345,10 +347,13 @@ describe('elements/content-sidebar/SidebarNavButton - Router Disabled', () => { fireEvent.click(button); expect(mockOnClick).toBeCalledWith('activity'); - expect(mockInternalSidebarNavigationHandler).toBeCalledWith({ - sidebar: 'activity', - open: true, - }, false); + expect(mockInternalSidebarNavigationHandler).toBeCalledWith( + { + sidebar: 'activity', + open: true, + }, + false, + ); }); test('calls internalSidebarNavigationHandler with replace=true when exact match', () => { @@ -364,10 +369,13 @@ describe('elements/content-sidebar/SidebarNavButton - Router Disabled', () => { fireEvent.click(button); expect(mockOnClick).toBeCalledWith('activity'); - expect(mockInternalSidebarNavigationHandler).toBeCalledWith({ - sidebar: 'activity', - open: true, - }, true); + expect(mockInternalSidebarNavigationHandler).toBeCalledWith( + { + sidebar: 'activity', + open: true, + }, + true, + ); }); test('does not call internalSidebarNavigationHandler on right click', () => { From a60f67b33656e804d03af5046aa4a1e1874d2d23 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Mon, 1 Dec 2025 16:37:40 -0500 Subject: [PATCH 07/14] feat(preview-modernization): fix merge conflicts --- src/elements/content-sidebar/SidebarNav.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index 83a2f783d4..e29d323e11 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -9,7 +9,6 @@ import { injectIntl } from 'react-intl'; import type { IntlShape } from 'react-intl'; import classNames from 'classnames'; import noop from 'lodash/noop'; -import classNames from 'classnames'; import { BoxAiLogo, BoxAiLogo24 } from '@box/blueprint-web-assets/icons/Logo'; import { Size6, Size5, IconIconBlue } from '@box/blueprint-web-assets/tokens/tokens'; import { usePromptFocus } from '@box/box-ai-content-answers'; From 611388c5832d86559c4ba0e2f92021ecb3b39fce Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Mon, 1 Dec 2025 17:52:27 -0500 Subject: [PATCH 08/14] feat(preview-modernization): more flow fixes --- flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js b/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js index 9edc77abd2..414a90f029 100644 --- a/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js +++ b/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js @@ -9,6 +9,8 @@ declare module '@box/blueprint-web-assets/icons/Medium' { declare export var XMark: React$ComponentType; declare export var BoxAiAdvancedLogo24: React$ComponentType; declare export var BoxAiLogo24: React$ComponentType; + declare export var Comment: React$ComponentType; + declare export var Metadata: React$ComponentType; } declare module '@box/blueprint-web-assets/icons/Content' { @@ -37,6 +39,7 @@ declare module '@box/blueprint-web-assets/icons/Fill' { declare module '@box/blueprint-web-assets/icons/Logo' { declare export var BoxLogo: React$ComponentType; declare export var BoxAiLogo: React$ComponentType; + declare export var BoxAiLogo24: React$ComponentType; } declare module '@box/blueprint-web-assets/illustrations/Medium' { @@ -56,4 +59,5 @@ declare module '@box/blueprint-web-assets/tokens/tokens' { declare export var Gray50: any; declare export var Size3: any; declare export var Size6: any; + declare export var IconIconBlue: any; } From be2d82ae6e04c3d4069566a3722528e12178c792 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 11:51:01 -0500 Subject: [PATCH 09/14] feat(preview-modernization): fix more flow errors --- .../npm/@box/blueprint-web-assets_vx.x.x.js | 8 ++++++-- src/elements/content-sidebar/SidebarNav.js | 20 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js b/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js index 414a90f029..e2a1e28542 100644 --- a/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js +++ b/flow-typed/npm/@box/blueprint-web-assets_vx.x.x.js @@ -7,12 +7,16 @@ declare module '@box/blueprint-web-assets/icons/Medium' { declare export var AlertCircle: React$ComponentType; declare export var AlertTriangle: React$ComponentType; declare export var XMark: React$ComponentType; - declare export var BoxAiAdvancedLogo24: React$ComponentType; - declare export var BoxAiLogo24: React$ComponentType; declare export var Comment: React$ComponentType; declare export var Metadata: React$ComponentType; } +declare module '@box/blueprint-web-assets/icons/MediumFilled' { + declare export var Comment: React$ComponentType; + declare export var InformationCircle: React$ComponentType; + declare export var Metadata: React$ComponentType; +} + declare module '@box/blueprint-web-assets/icons/Content' { declare export var FolderExternal: React$ComponentType; declare export var FolderPersonal: React$ComponentType; diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index e29d323e11..1ac7cb9cc0 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -10,14 +10,18 @@ import type { IntlShape } from 'react-intl'; import classNames from 'classnames'; import noop from 'lodash/noop'; import { BoxAiLogo, BoxAiLogo24 } from '@box/blueprint-web-assets/icons/Logo'; +import { + Comment as CommentIcon, + InformationCircle as InformationCircleIcon, + Metadata as MetadataIcon, +} from '@box/blueprint-web-assets/icons/Medium'; +import { + Comment as CommentIconFilled, + InformationCircle as InformationCircleIconFilled, + Metadata as MetadataIconFilled, +} from '@box/blueprint-web-assets/icons/MediumFilled'; import { Size6, Size5, IconIconBlue } from '@box/blueprint-web-assets/tokens/tokens'; import { usePromptFocus } from '@box/box-ai-content-answers'; -import CommentIcon from '@box/blueprint-web-assets/icons/Medium/Comment'; -import CommentIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/Comment'; -import InfoIcon from '@box/blueprint-web-assets/icons/Medium/InformationCircle'; -import InfoIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/InformationCircle'; -import MetadataIcon from '@box/blueprint-web-assets/icons/Medium/Metadata'; -import MetadataIconFilled from '@box/blueprint-web-assets/icons/MediumFilled/Metadata'; import AdditionalTabs from './additional-tabs'; import DocGenIcon from '../../icon/fill/DocGenIcon'; import IconChatRound from '../../icons/general/IconChatRound'; @@ -123,9 +127,9 @@ const SidebarNav = ({ return ; } return isActive ? ( - + ) : ( - + ); }; From 0a058f326f1398ad9a8b24b0b033191f28cae80f Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 12:12:17 -0500 Subject: [PATCH 10/14] feat(preview-modernization): PR feedback --- src/elements/content-sidebar/_mixins.scss | 4 ++-- .../content-sidebar/additional-tabs/AdditionalTabs.scss | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/elements/content-sidebar/_mixins.scss b/src/elements/content-sidebar/_mixins.scss index 84d4c4d67c..26f518fcc4 100644 --- a/src/elements/content-sidebar/_mixins.scss +++ b/src/elements/content-sidebar/_mixins.scss @@ -28,8 +28,8 @@ } @mixin bdl-SidebarNavIconModernized { - width: 20px; - height: 20px; + width: var(--size-5); + height: var(--size-5); } @mixin bcs-SidebarSection { diff --git a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss index 85d29cdceb..ce0999e997 100644 --- a/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss +++ b/src/elements/content-sidebar/additional-tabs/AdditionalTabs.scss @@ -4,7 +4,7 @@ display: flex; flex-direction: column; - &--modernized { + &.bdl-AdditionalTabs--modernized { .bdl-AdditionalTab-icon, .bdl-AdditionalTabPlaceholder-icon { @include bdl-SidebarNavIconModernized; From ec9f09bf44a5a59d48595d21cda8840035219b32 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 12:20:04 -0500 Subject: [PATCH 11/14] feat(preview-modernization): move icon wrappers outside of component --- src/elements/content-sidebar/SidebarNav.js | 92 +++++++++++++--------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index 1ac7cb9cc0..096923f12d 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -74,6 +74,58 @@ type Props = { signSidebarProps: SignSidebarProps, }; +// Icon wrapper components that receive isActive prop from SidebarNavButton +const ActivityIconWrapper = ({ + isActive, + isPreviewModernizationEnabled, +}: { + isActive?: boolean, + isPreviewModernizationEnabled: boolean, +}) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); +}; + +const DetailsIconWrapper = ({ + isActive, + isPreviewModernizationEnabled, +}: { + isActive?: boolean, + isPreviewModernizationEnabled: boolean, +}) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); +}; + +const MetadataIconWrapper = ({ + isActive, + isPreviewModernizationEnabled, +}: { + isActive?: boolean, + isPreviewModernizationEnabled: boolean, +}) => { + if (!isPreviewModernizationEnabled) { + return ; + } + return isActive ? ( + + ) : ( + + ); +}; + const SidebarNav = ({ additionalTabs, elementId, @@ -110,40 +162,6 @@ const SidebarNav = ({ } }; - // Icon wrapper components that receive isActive prop from SidebarNavButton - const ActivityIconWrapper = ({ isActive }: { isActive?: boolean }) => { - if (!isPreviewModernizationEnabled) { - return ; - } - return isActive ? ( - - ) : ( - - ); - }; - - const DetailsIconWrapper = ({ isActive }: { isActive?: boolean }) => { - if (!isPreviewModernizationEnabled) { - return ; - } - return isActive ? ( - - ) : ( - - ); - }; - - const MetadataIconWrapper = ({ isActive }: { isActive?: boolean }) => { - if (!isPreviewModernizationEnabled) { - return ; - } - return isActive ? ( - - ) : ( - - ); - }; - return (
- + )} {hasDetails && ( @@ -205,7 +223,7 @@ const SidebarNav = ({ sidebarView={SIDEBAR_VIEW_DETAILS} tooltip={intl.formatMessage(messages.sidebarDetailsTitle)} > - + )} {hasSkills && ( @@ -231,7 +249,7 @@ const SidebarNav = ({ sidebarView={SIDEBAR_VIEW_METADATA} tooltip={intl.formatMessage(messages.sidebarMetadataTitle)} > - + )} {hasDocGen && ( From e5c4023db3178b0fd178f2502fd1a2f5af8a6fb0 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 12:23:53 -0500 Subject: [PATCH 12/14] feat(preview-modernization): refactor props in sidebarnav --- src/elements/content-sidebar/SidebarNav.js | 67 +++++++++------------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/src/elements/content-sidebar/SidebarNav.js b/src/elements/content-sidebar/SidebarNav.js index 096923f12d..208aec84ca 100644 --- a/src/elements/content-sidebar/SidebarNav.js +++ b/src/elements/content-sidebar/SidebarNav.js @@ -53,35 +53,13 @@ const SIDEBAR_TAB_ICON_PROPS = { width: Size5, }; -type Props = { - additionalTabs?: Array, - elementId: string, - fileId: string, - hasActivity: boolean, - hasAdditionalTabs: boolean, - hasBoxAI: boolean, - hasDetails: boolean, - hasDocGen?: boolean, - hasMetadata: boolean, - hasSkills: boolean, - internalSidebarNavigation?: InternalSidebarNavigation, - internalSidebarNavigationHandler?: InternalSidebarNavigationHandler, - intl: IntlShape, - isOpen?: boolean, - onNavigate?: (SyntheticEvent<>, NavigateOptions) => void, - onPanelChange?: (name: string, isInitialState: boolean) => void, - routerDisabled?: boolean, - signSidebarProps: SignSidebarProps, +type IconWrapperProps = { + isActive?: boolean, + isPreviewModernizationEnabled: boolean, }; // Icon wrapper components that receive isActive prop from SidebarNavButton -const ActivityIconWrapper = ({ - isActive, - isPreviewModernizationEnabled, -}: { - isActive?: boolean, - isPreviewModernizationEnabled: boolean, -}) => { +const ActivityIconWrapper = ({ isActive, isPreviewModernizationEnabled }: IconWrapperProps) => { if (!isPreviewModernizationEnabled) { return ; } @@ -92,13 +70,7 @@ const ActivityIconWrapper = ({ ); }; -const DetailsIconWrapper = ({ - isActive, - isPreviewModernizationEnabled, -}: { - isActive?: boolean, - isPreviewModernizationEnabled: boolean, -}) => { +const DetailsIconWrapper = ({ isActive, isPreviewModernizationEnabled }: IconWrapperProps) => { if (!isPreviewModernizationEnabled) { return ; } @@ -109,13 +81,7 @@ const DetailsIconWrapper = ({ ); }; -const MetadataIconWrapper = ({ - isActive, - isPreviewModernizationEnabled, -}: { - isActive?: boolean, - isPreviewModernizationEnabled: boolean, -}) => { +const MetadataIconWrapper = ({ isActive, isPreviewModernizationEnabled }: IconWrapperProps) => { if (!isPreviewModernizationEnabled) { return ; } @@ -126,6 +92,27 @@ const MetadataIconWrapper = ({ ); }; +type Props = { + additionalTabs?: Array, + elementId: string, + fileId: string, + hasActivity: boolean, + hasAdditionalTabs: boolean, + hasBoxAI: boolean, + hasDetails: boolean, + hasDocGen?: boolean, + hasMetadata: boolean, + hasSkills: boolean, + internalSidebarNavigation?: InternalSidebarNavigation, + internalSidebarNavigationHandler?: InternalSidebarNavigationHandler, + intl: IntlShape, + isOpen?: boolean, + onNavigate?: (SyntheticEvent<>, NavigateOptions) => void, + onPanelChange?: (name: string, isInitialState: boolean) => void, + routerDisabled?: boolean, + signSidebarProps: SignSidebarProps, +}; + const SidebarNav = ({ additionalTabs, elementId, From 45f45108952a8ba31e09eb144e4f77ecc2c899b5 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 14:33:28 -0500 Subject: [PATCH 13/14] feat(preview-modernization): alphabetize props --- src/elements/content-sidebar/SidebarNavButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elements/content-sidebar/SidebarNavButton.js b/src/elements/content-sidebar/SidebarNavButton.js index f64f5979bb..a94b6c5f34 100644 --- a/src/elements/content-sidebar/SidebarNavButton.js +++ b/src/elements/content-sidebar/SidebarNavButton.js @@ -27,11 +27,11 @@ type Props = { internalSidebarNavigationHandler?: InternalSidebarNavigationHandler, isDisabled?: boolean, isOpen?: boolean, + isPreviewModernizationEnabled?: boolean, onClick?: (sidebarView: ViewTypeValues) => void, routerDisabled?: boolean, sidebarView: ViewTypeValues, tooltip: React.Node, - isPreviewModernizationEnabled?: boolean, }; const SidebarNavButton = React.forwardRef>((props: Props, ref: React.Ref) => { From 6edfd4d8261d005e78c7f610be98dbc58e57e432 Mon Sep 17 00:00:00 2001 From: Adam Horowitz Date: Tue, 2 Dec 2025 15:15:04 -0500 Subject: [PATCH 14/14] feat(preview-modernization): use state for sign dropdown --- .../content-sidebar/SidebarNavSign.tsx | 19 ++++++++++++++++++- .../content-sidebar/SidebarNavSignButton.tsx | 5 ++--- .../__tests__/SidebarNavSignButton.test.tsx | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/elements/content-sidebar/SidebarNavSign.tsx b/src/elements/content-sidebar/SidebarNavSign.tsx index 429a9517c8..5e532ffe75 100644 --- a/src/elements/content-sidebar/SidebarNavSign.tsx +++ b/src/elements/content-sidebar/SidebarNavSign.tsx @@ -34,10 +34,27 @@ export function SidebarNavSign(signSidebarProps: SignSidebarProps) { targetingApi: boxSignTargetingApi, } = signSidebarProps; + const [isDropdownOpen, setIsDropdownOpen] = React.useState(false); + + const handleOnDropdownOpen = () => { + setIsDropdownOpen(true); + }; + + const handleOnDropdownClose = () => { + setIsDropdownOpen(false); + }; + return ( - + diff --git a/src/elements/content-sidebar/SidebarNavSignButton.tsx b/src/elements/content-sidebar/SidebarNavSignButton.tsx index 9e9f83974a..1090bd9813 100644 --- a/src/elements/content-sidebar/SidebarNavSignButton.tsx +++ b/src/elements/content-sidebar/SidebarNavSignButton.tsx @@ -17,6 +17,7 @@ import './SidebarNavSignButton.scss'; export type Props = PlainButtonProps & { blockedReason?: string; + isDropdownOpen: boolean; intl: IntlShape; targetingApi?: { canShow: boolean; @@ -28,7 +29,7 @@ export type Props = PlainButtonProps & { export const PlaceholderTooltip = ({ children }: { children: React.ReactNode }) => children; -export function SidebarNavSignButton({ blockedReason, intl, targetingApi, ...rest }: Props) { +export function SidebarNavSignButton({ blockedReason, intl, isDropdownOpen, targetingApi, ...rest }: Props) { const isSignDisabled = !!blockedReason; const isTargeted = targetingApi?.canShow; const FtuxTooltip = !isSignDisabled && isTargeted ? TargetedClickThroughGuideTooltip : PlaceholderTooltip; @@ -51,8 +52,6 @@ export function SidebarNavSignButton({ blockedReason, intl, targetingApi, ...res } const renderButtonWithTooltip = () => { - const isDropdownOpen = rest['aria-expanded'] === 'true'; - // Use Blueprint tooltip when modernization is enabled if (isPreviewModernizationEnabled) { const modernizedButton = ( diff --git a/src/elements/content-sidebar/__tests__/SidebarNavSignButton.test.tsx b/src/elements/content-sidebar/__tests__/SidebarNavSignButton.test.tsx index 1c9306c9b9..dcb072c429 100644 --- a/src/elements/content-sidebar/__tests__/SidebarNavSignButton.test.tsx +++ b/src/elements/content-sidebar/__tests__/SidebarNavSignButton.test.tsx @@ -8,7 +8,7 @@ import TargetedClickThroughGuideTooltip from '../../../features/targeting/Target import Tooltip from '../../../components/tooltip'; describe('elements/content-sidebar/SidebarNavSignButton', () => { - const getWrapper = (props = {}) => shallow().dive(); + const getWrapper = (props = {}) => shallow().dive(); test('should render the correct label', () => { const wrapper = getWrapper();