diff --git a/build-tools/utils/themes.js b/build-tools/utils/themes.js index 5066477bbf..0c84eb7c2a 100644 --- a/build-tools/utils/themes.js +++ b/build-tools/utils/themes.js @@ -12,8 +12,8 @@ const themes = [ designTokensDir: 'design-tokens', designTokensPackageJson: { name: '@cloudscape-design/design-tokens' }, outputPath: path.join(workspace.targetPath, 'components'), - primaryThemePath: './classic/index.js', - secondaryThemePaths: ['./visual-refresh-secondary/index.js'], + primaryThemePath: './visual-refresh/index.js', + secondaryThemePaths: [], }, ]; diff --git a/package.json b/package.json index 58e39b7814..b75224a314 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "test:integ": "gulp test:integ", "test:motion": "gulp test:motion", "lint": "npm-run-all --parallel lint:*", - "lint:eslint": "eslint --ignore-path .gitignore --ext ts,tsx,js .", + "lint:eslint": "eslint --fix --ignore-path .gitignore --ext ts,tsx,js .", "lint:stylelint": "stylelint --ignore-path .gitignore --fix '{src,pages}/**/*.{css,scss}'", "start": "npm-run-all --parallel start:watch start:dev", "start:watch": "gulp watch", diff --git a/src/alert/__tests__/alert.test.tsx b/src/alert/__tests__/alert.test.tsx index ff89b3b9d8..1d27b3256e 100644 --- a/src/alert/__tests__/alert.test.tsx +++ b/src/alert/__tests__/alert.test.tsx @@ -8,14 +8,12 @@ import Alert, { AlertProps } from '../../../lib/components/alert'; import Button from '../../../lib/components/button'; import TestI18nProvider from '../../../lib/components/i18n/testing'; import { DATA_ATTR_ANALYTICS_ALERT } from '../../../lib/components/internal/analytics/selectors'; -import { useVisualRefresh } from '../../../lib/components/internal/hooks/use-visual-mode'; import createWrapper from '../../../lib/components/test-utils/dom'; import styles from '../../../lib/components/alert/styles.css.js'; jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ ...jest.requireActual('../../../lib/components/internal/hooks/use-visual-mode'), - useVisualRefresh: jest.fn().mockReturnValue(false), })); function renderAlert(props: AlertProps = {}) { @@ -31,10 +29,6 @@ const i18nStrings: AlertProps.I18nStrings = { dismissAriaLabel: 'dismiss', }; -beforeEach(() => { - jest.mocked(useVisualRefresh).mockReset(); -}); - describe('Alert Component', () => { describe('structure', () => { it('has no header container when no header is set', () => { @@ -173,23 +167,7 @@ describe('Alert Component', () => { }); describe('icon size', () => { - test('classic - big if has header and content', () => { - const { wrapper } = renderAlert({ header: 'Header', children: ['Content'] }); - expect(wrapper.findByClassName(styles['icon-size-normal'])).toBeFalsy(); - expect(wrapper.findByClassName(styles['icon-size-big'])).toBeTruthy(); - }); - test('classic - normal if only header', () => { - const { wrapper } = renderAlert({ header: 'Header' }); - expect(wrapper.findByClassName(styles['icon-size-big'])).toBeFalsy(); - expect(wrapper.findByClassName(styles['icon-size-normal'])).toBeTruthy(); - }); - test('classic - normal if only content', () => { - const { wrapper } = renderAlert({ children: ['Content'] }); - expect(wrapper.findByClassName(styles['icon-size-big'])).toBeFalsy(); - expect(wrapper.findByClassName(styles['icon-size-normal'])).toBeTruthy(); - }); test('visual refresh - always normal', () => { - jest.mocked(useVisualRefresh).mockReturnValue(true); const { wrapper } = renderAlert({ header: 'Header', children: ['Content'] }); expect(wrapper.findByClassName(styles['icon-size-big'])).toBeFalsy(); expect(wrapper.findByClassName(styles['icon-size-normal'])).toBeTruthy(); diff --git a/src/alert/internal.tsx b/src/alert/internal.tsx index 4a62ddadbf..b599edb361 100644 --- a/src/alert/internal.tsx +++ b/src/alert/internal.tsx @@ -18,7 +18,6 @@ import { useContainerBreakpoints } from '../internal/hooks/container-queries'; import useForwardFocus from '../internal/hooks/forward-focus'; import { InternalBaseComponentProps } from '../internal/hooks/use-base-component'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; import { awsuiPluginsInternal } from '../internal/plugins/api'; import { createUseDiscoveredAction, createUseDiscoveredContent } from '../internal/plugins/helpers'; import { SomeRequired } from '../internal/types'; @@ -84,13 +83,7 @@ const InternalAlert = React.forwardRef( const headerRef = useMergeRefs(headerRefAction, headerRefContent); const contentRef = useMergeRefs(contentRefAction, contentRefContent); - const isRefresh = useVisualRefresh(); - const size = isRefresh - ? 'normal' - : headerReplacementType !== 'remove' && header && contentReplacementType !== 'remove' && children - ? 'big' - : 'normal'; - + const size = 'normal'; const hasAction = Boolean(action || buttonText || discoveredActions.length); const analyticsAttributes = { diff --git a/src/app-layout/__tests__/background-overlap.test.tsx b/src/app-layout/__tests__/background-overlap.test.tsx index ab51d70b00..ba9489e8d1 100644 --- a/src/app-layout/__tests__/background-overlap.test.tsx +++ b/src/app-layout/__tests__/background-overlap.test.tsx @@ -11,7 +11,6 @@ import { useDynamicOverlap } from '../../../lib/components/internal/hooks/use-dy jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ ...jest.requireActual('../../../lib/components/internal/hooks/use-visual-mode'), - useVisualRefresh: jest.fn().mockReturnValue(true), })); let positiveHeight = true; diff --git a/src/app-layout/__tests__/desktop.test.tsx b/src/app-layout/__tests__/desktop.test.tsx index df63cc35ee..db6aac54c0 100644 --- a/src/app-layout/__tests__/desktop.test.tsx +++ b/src/app-layout/__tests__/desktop.test.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 /* eslint simple-import-sort/imports: 0 */ import React from 'react'; -import { act, fireEvent, screen, within } from '@testing-library/react'; +import { act } from '@testing-library/react'; import { describeEachAppLayout, @@ -18,10 +18,8 @@ import notificationStyles from '../../../lib/components/app-layout/notifications import visualRefreshStyles from '../../../lib/components/app-layout/visual-refresh/styles.css.js'; import visualRefreshToolbarNotificationStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/notifications/styles.css.js'; import toolbarStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/styles.css.js'; -import drawerStyles from '../../../lib/components/app-layout/drawer/styles.css.js'; import customCssProps from '../../../lib/components/internal/generated/custom-css-properties'; import { KeyCode } from '../../internal/keycode'; -import { useVisualRefresh } from '../../../lib/components/internal/hooks/use-visual-mode'; jest.mock('@cloudscape-design/component-toolkit', () => ({ ...jest.requireActual('@cloudscape-design/component-toolkit'), @@ -252,64 +250,6 @@ describeEachAppLayout({ sizes: ['desktop'] }, ({ theme }) => { }); }); -describe('Classic only features', () => { - beforeEach(() => { - (useVisualRefresh as jest.Mock).mockReturnValue(false); - }); - afterEach(() => { - (useVisualRefresh as jest.Mock).mockReset(); - }); - - test(`should toggle single drawer on click of container`, () => { - const { wrapper } = renderComponent( - - ); - fireEvent.click(screen.getByLabelText('Drawers')); - expect(wrapper.findActiveDrawer()).toBeTruthy(); - fireEvent.click(screen.getByLabelText('Drawers')); - expect(wrapper.findActiveDrawer()).toBeFalsy(); - }); - - test(`should not toggle many drawers on click of container`, () => { - const { wrapper } = renderComponent( - - ); - fireEvent.click(screen.getByLabelText('Drawers')); - expect(wrapper.findActiveDrawer()).toBeFalsy(); - }); - - test('renders roles only when aria labels are not provided', () => { - const { wrapper } = renderComponent(); - const drawersAside = within(wrapper.findByClassName(drawerStyles['drawer-closed'])!.getElement()).getByRole( - 'region' - ); - - expect(wrapper.findDrawerTriggerById(testDrawer.id)!.getElement()).not.toHaveAttribute('aria-label'); - expect(drawersAside).not.toHaveAttribute('aria-label'); - expect(wrapper.findByClassName(drawerStyles['drawer-triggers-wrapper'])!.getElement()).toHaveAttribute( - 'role', - 'toolbar' - ); - }); - - test('renders roles and aria labels when provided', () => { - const { wrapper } = renderComponent(); - const drawersAside = within(wrapper.findByClassName(drawerStyles['drawer-closed'])!.getElement()).getByRole( - 'region' - ); - - expect(wrapper.findDrawerTriggerById('security')!.getElement()).toHaveAttribute( - 'aria-label', - 'Security trigger button' - ); - expect(drawersAside).toHaveAttribute('aria-label', 'Drawers'); - expect(wrapper.findByClassName(drawerStyles['drawer-triggers-wrapper'])!.getElement()).toHaveAttribute( - 'role', - 'toolbar' - ); - }); -}); - describeEachAppLayout({ themes: ['refresh', 'refresh-toolbar'], sizes: ['desktop'] }, ({ theme }) => { const styles = theme === 'refresh' ? visualRefreshStyles : toolbarStyles; test('renders roles only when aria labels are not provided', () => { diff --git a/src/app-layout/__tests__/header-variant.test.tsx b/src/app-layout/__tests__/header-variant.test.tsx index 7047bb8afe..53091f226d 100644 --- a/src/app-layout/__tests__/header-variant.test.tsx +++ b/src/app-layout/__tests__/header-variant.test.tsx @@ -11,10 +11,6 @@ import { describeEachAppLayout, renderComponent } from './utils'; import visualRefreshStyles from '../../../lib/components/app-layout/visual-refresh/styles.css.js'; import toolbarSkeletonStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/skeleton/styles.css.js'; -jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ - useVisualRefresh: jest.fn().mockReturnValue(false), -})); - jest.mock('../../../lib/components/internal/hooks/use-mobile', () => ({ useMobile: jest.fn().mockReturnValue(false), })); diff --git a/src/app-layout/__tests__/split-panel.test.tsx b/src/app-layout/__tests__/split-panel.test.tsx index b9660a738b..d35e0cf363 100644 --- a/src/app-layout/__tests__/split-panel.test.tsx +++ b/src/app-layout/__tests__/split-panel.test.tsx @@ -7,7 +7,6 @@ import AppLayout from '../../../lib/components/app-layout'; import { AppLayoutProps } from '../../../lib/components/app-layout/interfaces'; import SplitPanel from '../../../lib/components/split-panel'; import { KeyCode } from '../../../lib/components/internal/keycode'; -import { useVisualRefresh } from '../../../lib/components/internal/hooks/use-visual-mode'; import { describeEachAppLayout, renderComponent, splitPanelI18nStrings } from './utils'; import applayoutTools from '../../../lib/components/app-layout/visual-refresh/styles.selectors.js'; import { AppLayoutWrapper } from '../../../lib/components/test-utils/dom'; @@ -30,10 +29,6 @@ const fakeComputedStyle: Window['getComputedStyle'] = (...args) => { return result; }; -jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ - useVisualRefresh: jest.fn().mockReturnValue(false), -})); - jest.mock('@cloudscape-design/component-toolkit/internal', () => ({ ...jest.requireActual('@cloudscape-design/component-toolkit/internal'), isMotionDisabled: jest.fn().mockReturnValue(true), @@ -262,13 +257,6 @@ describeEachAppLayout({ sizes: ['desktop'] }, ({ theme }) => { }); describe('Visual refresh only features', () => { - beforeEach(() => { - (useVisualRefresh as jest.Mock).mockReturnValue(true); - }); - afterEach(() => { - (useVisualRefresh as jest.Mock).mockReset(); - }); - function isDrawersBarDisplayed(wrapper: AppLayoutWrapper) { return !!wrapper.findByClassName(applayoutTools['has-tools-form']); } diff --git a/src/app-layout/__tests__/utils.tsx b/src/app-layout/__tests__/utils.tsx index e31ca383fa..1803512d9b 100644 --- a/src/app-layout/__tests__/utils.tsx +++ b/src/app-layout/__tests__/utils.tsx @@ -9,7 +9,6 @@ import { ComponentWrapper } from '@cloudscape-design/test-utils-core/dom'; import AppLayout, { AppLayoutProps } from '../../../lib/components/app-layout'; import customCssProps from '../../../lib/components/internal/generated/custom-css-properties'; import { useMobile } from '../../../lib/components/internal/hooks/use-mobile'; -import { useVisualRefresh } from '../../../lib/components/internal/hooks/use-visual-mode'; import { SplitPanelProps } from '../../../lib/components/split-panel'; import createWrapper, { AppLayoutWrapper, ElementWrapper } from '../../../lib/components/test-utils/dom'; @@ -22,10 +21,6 @@ jest.mock('../../../lib/components/internal/hooks/use-mobile', () => ({ useMobile: jest.fn().mockReturnValue(true), })); -jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ - useVisualRefresh: jest.fn().mockReturnValue(false), -})); - jest.mock('@cloudscape-design/component-toolkit/internal', () => ({ ...jest.requireActual('@cloudscape-design/component-toolkit/internal'), isMotionDisabled: jest.fn().mockReturnValue(true), @@ -53,7 +48,7 @@ interface AppLayoutTestConfig { type AppLayoutTestSuite = (config: { theme: Theme; size: Size }) => void; const defaultTestConfig: AppLayoutTestConfig = { - themes: ['classic', 'refresh', 'refresh-toolbar'], + themes: ['refresh', 'refresh-toolbar'], sizes: ['desktop', 'mobile'], }; @@ -70,12 +65,10 @@ export function describeEachAppLayout( describe(`Theme=${theme}, Size=${size}`, () => { beforeEach(() => { (useMobile as jest.Mock).mockReturnValue(size === 'mobile'); - (useVisualRefresh as jest.Mock).mockReturnValue(theme !== 'classic'); setGlobalFlag('appLayoutWidget', theme === 'refresh-toolbar'); }); afterEach(() => { (useMobile as jest.Mock).mockReset(); - (useVisualRefresh as jest.Mock).mockReset(); setGlobalFlag('appLayoutWidget', undefined); }); test('mocks applied correctly', () => { diff --git a/src/app-layout/classic.tsx b/src/app-layout/classic.tsx deleted file mode 100644 index 5d77d30fea..0000000000 --- a/src/app-layout/classic.tsx +++ /dev/null @@ -1,610 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 -import React, { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; -import clsx from 'clsx'; - -import { useContainerQuery } from '@cloudscape-design/component-toolkit'; -import { findUpUntil } from '@cloudscape-design/component-toolkit/dom'; -import { useStableCallback } from '@cloudscape-design/component-toolkit/internal'; - -import { SplitPanelSideToggleProps } from '../internal/context/split-panel-context'; -import { fireNonCancelableEvent } from '../internal/events'; -import { useControllable } from '../internal/hooks/use-controllable'; -import { useMobile } from '../internal/hooks/use-mobile'; -import { - CONSTRAINED_MAIN_PANEL_MIN_HEIGHT, - CONSTRAINED_PAGE_HEIGHT, - getSplitPanelDefaultSize, - MAIN_PANEL_MIN_HEIGHT, -} from '../split-panel/utils/size-utils'; -import ContentWrapper, { ContentWrapperProps } from './content-wrapper'; -import { Drawer, DrawerTriggersBar } from './drawer'; -import { ResizableDrawer } from './drawer/resizable-drawer'; -import { AppLayoutProps, AppLayoutPropsWithDefaults } from './interfaces'; -import { MobileToolbar } from './mobile-toolbar'; -import { Notifications } from './notifications'; -import { SideSplitPanelDrawer, SplitPanelProvider, SplitPanelProviderProps } from './split-panel'; -import { shouldSplitPanelBeForcedToBottom } from './split-panel/split-panel-forced-position'; -import { togglesConfig } from './toggles'; -import { getStickyOffsetVars } from './utils/sticky-offsets'; -import { TOOLS_DRAWER_ID, useDrawers } from './utils/use-drawers'; -import { useFocusControl } from './utils/use-focus-control'; -import { useSplitPanelFocusControl } from './utils/use-split-panel-focus-control'; - -import styles from './styles.css.js'; -import testutilStyles from './test-classes/styles.css.js'; - -const ClassicAppLayout = React.forwardRef( - ( - { - navigation, - navigationWidth, - navigationHide, - navigationOpen, - tools, - toolsWidth, - toolsHide, - toolsOpen: controlledToolsOpen, - breadcrumbs, - notifications, - stickyNotifications, - contentHeader, - disableContentHeaderOverlap, - content, - contentType, - disableContentPaddings, - disableBodyScroll, - maxContentWidth, - minContentWidth, - placement, - ariaLabels, - splitPanel, - splitPanelSize: controlledSplitPanelSize, - splitPanelOpen: controlledSplitPanelOpen, - splitPanelPreferences: controlledSplitPanelPreferences, - onSplitPanelPreferencesChange, - onSplitPanelResize, - onSplitPanelToggle, - onNavigationChange, - onToolsChange, - drawers: controlledDrawers, - onDrawerChange, - activeDrawerId: controlledActiveDrawerId, - ...rest - }: AppLayoutPropsWithDefaults, - ref: React.Ref - ) => { - // Private API for embedded view mode - const __embeddedViewMode = Boolean((rest as any).__embeddedViewMode); - - const rootRef = useRef(null); - const isMobile = useMobile(); - - const [toolsOpen = false, setToolsOpen] = useControllable(controlledToolsOpen, onToolsChange, false, { - componentName: 'AppLayout', - controlledProp: 'toolsOpen', - changeHandler: 'onToolsChange', - }); - const onToolsToggle = (open: boolean) => { - setToolsOpen(open); - if (hasDrawers) { - focusDrawersButtons(); - } else { - focusToolsButtons(); - } - fireNonCancelableEvent(onToolsChange, { open }); - }; - - const { - drawers, - activeDrawer, - minDrawerSize, - activeDrawerSize, - activeDrawerId, - ariaLabelsWithDrawers, - onActiveDrawerChange, - onActiveDrawerResize, - } = useDrawers( - { - drawers: controlledDrawers, - onDrawerChange, - activeDrawerId: controlledActiveDrawerId, - ...rest, - }, - ariaLabels, - { - disableDrawersMerge: true, - ariaLabels, - tools, - toolsOpen, - toolsHide, - toolsWidth, - onToolsToggle, - } - ); - ariaLabels = ariaLabelsWithDrawers; - const hasDrawers = !!drawers; - - const { refs: navigationRefs, setFocus: focusNavButtons } = useFocusControl(navigationOpen); - const { - refs: toolsRefs, - setFocus: focusToolsButtons, - loseFocus: loseToolsFocus, - } = useFocusControl(toolsOpen || activeDrawer !== undefined, true); - const { - refs: drawerRefs, - setFocus: focusDrawersButtons, - loseFocus: loseDrawersFocus, - } = useFocusControl(!!activeDrawerId, true, activeDrawerId); - - const onNavigationToggle = useStableCallback((open: boolean) => { - focusNavButtons(); - fireNonCancelableEvent(onNavigationChange, { open }); - }); - - const onNavigationClick = (event: React.MouseEvent) => { - const hasLink = findUpUntil( - event.target as HTMLElement, - node => node.tagName === 'A' && !!(node as HTMLAnchorElement).href - ); - if (hasLink) { - onNavigationToggle(false); - } - }; - - useEffect(() => { - // Close navigation drawer on mobile so that the main content is visible - if (isMobile) { - onNavigationToggle(false); - } - }, [isMobile, onNavigationToggle]); - - const navigationVisible = !navigationHide && navigationOpen; - const toolsVisible = !toolsHide && toolsOpen; - - const [headerFooterHeight, setHeaderFooterHeight] = useState(0); - // Delay applying changes in header/footer height, as applying them immediately can cause - // ResizeOberver warnings due to the algorithm thinking that the change might have side-effects - // further up the tree, therefore blocking notifications to prevent loops - useEffect(() => { - const id = requestAnimationFrame(() => - setHeaderFooterHeight(placement.insetBlockStart + placement.insetBlockEnd) - ); - return () => cancelAnimationFrame(id); - }, [placement.insetBlockStart, placement.insetBlockEnd]); - const contentHeightStyle = { - [disableBodyScroll ? 'blockSize' : 'minBlockSize']: `calc(100vh - ${headerFooterHeight}px)`, - }; - - const [notificationsHeight, notificationsRef] = useContainerQuery(rect => rect.contentBoxHeight); - const anyPanelOpen = navigationVisible || toolsVisible || !!activeDrawer; - const hasRenderedNotifications = notificationsHeight ? notificationsHeight > 0 : false; - const stickyNotificationsHeight = stickyNotifications ? notificationsHeight ?? 0 : 0; - - const [splitPanelPreferences, setSplitPanelPreferences] = useControllable( - controlledSplitPanelPreferences, - onSplitPanelPreferencesChange, - undefined, - { - componentName: 'AppLayout', - controlledProp: 'splitPanelPreferences', - changeHandler: 'onSplitPanelPreferencesChange', - } - ); - const [splitPanelOpen = false, setSplitPanelOpen] = useControllable( - controlledSplitPanelOpen, - onSplitPanelToggle, - false, - { - componentName: 'AppLayout', - controlledProp: 'splitPanelOpen', - changeHandler: 'onSplitPanelToggle', - } - ); - - const splitPanelPosition = splitPanelPreferences?.position || 'bottom'; - const [splitPanelReportedToggle, setSplitPanelReportedToggle] = useState({ - displayed: false, - ariaLabel: undefined, - }); - const splitPanelDisplayed = !!(splitPanel && (splitPanelReportedToggle.displayed || splitPanelOpen)); - - const closedDrawerWidth = 40; - const effectiveNavigationWidth = navigationHide ? 0 : navigationOpen ? navigationWidth : closedDrawerWidth; - - const defaultSplitPanelSize = getSplitPanelDefaultSize(splitPanelPosition); - const [splitPanelSize = defaultSplitPanelSize, setSplitPanelSize] = useControllable( - controlledSplitPanelSize, - onSplitPanelResize, - defaultSplitPanelSize, - { - componentName: 'AppLayout', - controlledProp: 'splitPanelSize', - changeHandler: 'onSplitPanelResize', - } - ); - - const mainContentRef = useRef(null); - const legacyScrollRootRef = useRef(null); - - const { refs: splitPanelRefs, setLastInteraction: setSplitPanelLastInteraction } = useSplitPanelFocusControl([ - splitPanelPreferences, - splitPanelOpen, - ]); - - const onSplitPanelPreferencesSet = useCallback( - (detail: { position: 'side' | 'bottom' }) => { - setSplitPanelPreferences(detail); - setSplitPanelLastInteraction({ type: 'position' }); - fireNonCancelableEvent(onSplitPanelPreferencesChange, detail); - }, - [setSplitPanelPreferences, onSplitPanelPreferencesChange, setSplitPanelLastInteraction] - ); - const onSplitPanelSizeSet = useCallback( - (newSize: number) => { - setSplitPanelSize(newSize); - fireNonCancelableEvent(onSplitPanelResize, { size: newSize }); - }, - [setSplitPanelSize, onSplitPanelResize] - ); - - const onSplitPanelToggleHandler = useCallback(() => { - setSplitPanelOpen(!splitPanelOpen); - setSplitPanelLastInteraction({ type: splitPanelOpen ? 'close' : 'open' }); - fireNonCancelableEvent(onSplitPanelToggle, { open: !splitPanelOpen }); - }, [setSplitPanelOpen, splitPanelOpen, onSplitPanelToggle, setSplitPanelLastInteraction]); - - const getSplitPanelMaxHeight = useStableCallback(() => { - if (typeof document === 'undefined') { - return 0; // render the split panel in its minimum possible size - } else if (disableBodyScroll && legacyScrollRootRef.current) { - const availableHeight = legacyScrollRootRef.current.clientHeight; - return availableHeight < CONSTRAINED_PAGE_HEIGHT ? availableHeight : availableHeight - MAIN_PANEL_MIN_HEIGHT; - } else { - const availableHeight = - document.documentElement.clientHeight - placement.insetBlockStart - placement.insetBlockEnd; - return availableHeight < CONSTRAINED_PAGE_HEIGHT - ? availableHeight - CONSTRAINED_MAIN_PANEL_MIN_HEIGHT - : availableHeight - MAIN_PANEL_MIN_HEIGHT; - } - }); - - const rightDrawerBarWidth = drawers ? (drawers.length > 1 ? closedDrawerWidth : 0) : 0; - const contentPadding = 80; - // all content except split-panel + drawers/tools area - const resizableSpaceAvailable = Math.max( - 0, - placement.inlineSize - effectiveNavigationWidth - minContentWidth - contentPadding - rightDrawerBarWidth - ); - - const getEffectiveToolsWidth = () => { - if (activeDrawerSize && activeDrawer) { - return Math.min(resizableSpaceAvailable, activeDrawerSize); - } - - if (toolsHide || drawers) { - return 0; - } - - if (toolsOpen) { - return toolsWidth; - } - - return closedDrawerWidth; - }; - - const effectiveToolsWidth = getEffectiveToolsWidth(); - const availableWidthForSplitPanel = resizableSpaceAvailable - effectiveToolsWidth; - const isSplitPanelForcedPosition = shouldSplitPanelBeForcedToBottom({ - isMobile, - availableWidthForSplitPanel, - }); - const finalSplitPanePosition = isSplitPanelForcedPosition ? 'bottom' : splitPanelPosition; - - const splitPaneAvailableOnTheSide = splitPanelDisplayed && finalSplitPanePosition === 'side'; - - const sideSplitPanelSize = splitPaneAvailableOnTheSide ? (splitPanelOpen ? splitPanelSize : closedDrawerWidth) : 0; - const sideSplitPanelMaxWidth = Math.max(0, resizableSpaceAvailable - effectiveToolsWidth); - const drawerMaxSize = Math.max(0, resizableSpaceAvailable - sideSplitPanelSize); - - const navigationClosedWidth = navigationHide || isMobile ? 0 : closedDrawerWidth; - - const contentMaxWidthStyle = !isMobile ? { maxWidth: maxContentWidth } : undefined; - - const [splitPanelReportedSize, setSplitPanelReportedSize] = useState(0); - const [splitPanelReportedHeaderHeight, setSplitPanelReportedHeaderHeight] = useState(0); - - const splitPanelContextProps: SplitPanelProviderProps = { - topOffset: placement.insetBlockStart + (finalSplitPanePosition === 'bottom' ? stickyNotificationsHeight : 0), - bottomOffset: placement.insetBlockEnd, - leftOffset: - placement.insetInlineStart + - (isMobile ? 0 : !navigationHide && navigationOpen ? navigationWidth : navigationClosedWidth), - rightOffset: isMobile ? 0 : placement.insetInlineEnd + effectiveToolsWidth + rightDrawerBarWidth, - position: finalSplitPanePosition, - size: splitPanelSize, - maxWidth: sideSplitPanelMaxWidth, - getMaxHeight: getSplitPanelMaxHeight, - disableContentPaddings, - contentWidthStyles: contentMaxWidthStyle, - isOpen: splitPanelOpen, - isForcedPosition: isSplitPanelForcedPosition, - onResize: onSplitPanelSizeSet, - onToggle: onSplitPanelToggleHandler, - onPreferencesChange: onSplitPanelPreferencesSet, - setSplitPanelToggle: setSplitPanelReportedToggle, - reportSize: setSplitPanelReportedSize, - reportHeaderHeight: setSplitPanelReportedHeaderHeight, - refs: splitPanelRefs, - }; - const splitPanelWrapped = splitPanel && ( - - {finalSplitPanePosition === 'side' ? ( - {splitPanel} - ) : ( - splitPanel - )} - - ); - - const contentWrapperProps: ContentWrapperProps = { - contentType, - navigationPadding: navigationHide || !!navigationOpen, - contentWidthStyles: !isMobile ? { minWidth: minContentWidth, maxWidth: maxContentWidth } : undefined, - toolsPadding: - // tools padding is displayed in one of the three cases - // 1. Nothing on the that screen edge (no tools panel and no split panel) - toolsHide || - (hasDrawers && !activeDrawer && (!splitPanelDisplayed || finalSplitPanePosition !== 'side')) || - // 2. Tools panel is present and open - toolsVisible || - // 3. Split panel is open in side position - (splitPaneAvailableOnTheSide && splitPanelOpen), - isMobile, - }; - - useImperativeHandle(ref, () => ({ - openTools: () => onToolsToggle(true), - closeNavigationIfNecessary: () => { - if (isMobile) { - onNavigationToggle(false); - } - }, - focusToolsClose: () => { - if (hasDrawers) { - focusDrawersButtons(true); - } else { - focusToolsButtons(true); - } - }, - focusActiveDrawer: () => focusDrawersButtons(true), - focusSplitPanel: () => splitPanelRefs.slider.current?.focus(), - })); - - const splitPanelBottomOffset = - (!splitPanelDisplayed || finalSplitPanePosition !== 'bottom' - ? undefined - : splitPanelOpen - ? splitPanelReportedSize - : splitPanelReportedHeaderHeight) ?? undefined; - - const [mobileBarHeight, mobileBarRef] = useContainerQuery(rect => rect.contentBoxHeight); - - return ( -
- {isMobile && !__embeddedViewMode && (!toolsHide || !navigationHide || breadcrumbs) && ( - onNavigationToggle(true)} - onToolsOpen={() => onToolsToggle(true)} - unfocusable={anyPanelOpen} - mobileBarRef={mobileBarRef} - drawers={drawers} - activeDrawerId={activeDrawerId} - onDrawerChange={newDrawerId => { - onActiveDrawerChange(newDrawerId, { initiatedByUserAction: true }); - if (newDrawerId !== activeDrawerId) { - focusToolsButtons(); - focusDrawersButtons(); - } - }} - > - {breadcrumbs} - - )} -
- {!navigationHide && ( - - {navigation} - - )} -
-
- {notifications && ( - - {notifications} - - )} - {((!isMobile && breadcrumbs) || contentHeader) && ( - - {!isMobile && breadcrumbs && ( -
{breadcrumbs}
- )} - {contentHeader && ( -
- {contentHeader} -
- )} -
- )} - - {content} - -
- {finalSplitPanePosition === 'bottom' && splitPanelWrapped} -
- - {finalSplitPanePosition === 'side' && splitPanelWrapped} - - {hasDrawers ? ( - { - if (!isOpen) { - focusToolsButtons(); - focusDrawersButtons(); - onActiveDrawerChange(null, { initiatedByUserAction: true }); - } - }} - isOpen={true} - hideOpenButton={true} - toggleRefs={drawerRefs} - type="tools" - onLoseFocus={loseDrawersFocus} - activeDrawer={activeDrawer} - onResize={changeDetail => onActiveDrawerResize(changeDetail)} - refs={drawerRefs} - toolsContent={drawers?.find(drawer => drawer.id === TOOLS_DRAWER_ID)?.content} - > - {activeDrawer?.content} - - ) : ( - !toolsHide && ( - - {tools} - - ) - )} - {hasDrawers && drawers.length > 0 && ( - { - if (activeDrawerId !== newDrawerId) { - focusToolsButtons(); - focusDrawersButtons(); - } - onActiveDrawerChange(newDrawerId, { initiatedByUserAction: true }); - }} - ariaLabels={ariaLabels} - /> - )} -
-
- ); - } -); - -export default ClassicAppLayout; diff --git a/src/app-layout/defaults.ts b/src/app-layout/defaults.ts index 98191e5882..ed7c367bf4 100644 --- a/src/app-layout/defaults.ts +++ b/src/app-layout/defaults.ts @@ -45,12 +45,9 @@ interface AppLayoutState { export function applyDefaults( contentType: AppLayoutProps.ContentType, - stateFromProps: Pick, - isRefresh: boolean + stateFromProps: Pick ): AppLayoutState { - const contentTypeDefaults = isRefresh - ? { ...defaults[contentType], maxContentWidth: undefined } - : defaults[contentType]; + const contentTypeDefaults = { ...defaults[contentType], maxContentWidth: undefined }; return { maxContentWidth: stateFromProps.maxContentWidth ?? contentTypeDefaults.maxContentWidth, diff --git a/src/app-layout/index.tsx b/src/app-layout/index.tsx index ecbe700a97..4d5a2d83d8 100644 --- a/src/app-layout/index.tsx +++ b/src/app-layout/index.tsx @@ -11,7 +11,6 @@ import useBaseComponent from '../internal/hooks/use-base-component'; import { useControllable } from '../internal/hooks/use-controllable'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; import { useMobile } from '../internal/hooks/use-mobile'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; import { isDevelopment } from '../internal/is-development'; import { applyDisplayName } from '../internal/utils/apply-display-name'; import { applyDefaults } from './defaults'; @@ -69,7 +68,6 @@ const AppLayout = React.forwardRef( }, analyticsMetadata ); - const isRefresh = useVisualRefresh(); const isMobile = useMobile(); const i18n = useInternalI18n('app-layout'); @@ -85,11 +83,10 @@ const AppLayout = React.forwardRef( drawersOverflow: i18n('ariaLabels.drawersOverflow', rest.ariaLabels?.drawersOverflow), drawersOverflowWithBadge: i18n('ariaLabels.drawersOverflowWithBadge', rest.ariaLabels?.drawersOverflowWithBadge), }; - const { navigationOpen: defaultNavigationOpen, ...restDefaults } = applyDefaults( - contentType, - { maxContentWidth, minContentWidth }, - isRefresh - ); + const { navigationOpen: defaultNavigationOpen, ...restDefaults } = applyDefaults(contentType, { + maxContentWidth, + minContentWidth, + }); const [navigationOpen = false, setNavigationOpen] = useControllable( controlledNavigationOpen, diff --git a/src/app-layout/internal.tsx b/src/app-layout/internal.tsx index 033d14ad76..b4f8fd1e10 100644 --- a/src/app-layout/internal.tsx +++ b/src/app-layout/internal.tsx @@ -2,22 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import React from 'react'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; -import ClassicAppLayout from './classic'; import { AppLayoutProps, AppLayoutPropsWithDefaults } from './interfaces'; -import { useAppLayoutToolbarEnabled } from './utils/feature-flags'; -import RefreshedAppLayout from './visual-refresh'; import ToolbarAppLayout from './visual-refresh-toolbar'; export const AppLayoutInternal = React.forwardRef((props, ref) => { - const isRefresh = useVisualRefresh(); - const isToolbar = useAppLayoutToolbarEnabled(); - if (isRefresh) { - if (isToolbar) { - return ; - } else { - return ; - } - } - return ; + return ; }); diff --git a/src/app-layout/utils/feature-flags.ts b/src/app-layout/utils/feature-flags.ts index ac4ed1857f..9fbcd6a4cb 100644 --- a/src/app-layout/utils/feature-flags.ts +++ b/src/app-layout/utils/feature-flags.ts @@ -2,9 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 import { getGlobalFlag } from '@cloudscape-design/component-toolkit/internal'; -import { useVisualRefresh } from '../../internal/hooks/use-visual-mode'; - export const useAppLayoutToolbarEnabled = () => { - const isRefresh = useVisualRefresh(); - return isRefresh && (getGlobalFlag('appLayoutWidget') || getGlobalFlag('appLayoutToolbar')); + return getGlobalFlag('appLayoutWidget') || getGlobalFlag('appLayoutToolbar'); }; diff --git a/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx b/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx index 05df669387..52e4653bca 100644 --- a/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx +++ b/src/breadcrumb-group/__tests__/widgetized-breadcrumbs.test.tsx @@ -8,7 +8,6 @@ import { createWidgetizedBreadcrumbGroup } from '../../../lib/components/breadcr import { InternalBreadcrumbGroupProps } from '../../../lib/components/breadcrumb-group/interfaces'; import { BreadcrumbGroupSkeleton } from '../../../lib/components/breadcrumb-group/skeleton'; import { DATA_ATTR_RESOURCE_TYPE, getFunnelNameSelector } from '../../../lib/components/internal/analytics/selectors'; -import { useVisualRefresh } from '../../../lib/components/internal/hooks/use-visual-mode'; import { FunctionComponent } from '../../../lib/components/internal/widgets'; import createWrapper from '../../../lib/components/test-utils/dom'; import { describeWithAppLayoutFeatureFlagEnabled } from '../../internal/widgets/__tests__/utils'; @@ -44,28 +43,7 @@ function getResourceTypeElements(container: HTMLElement) { return container.querySelectorAll(`[${DATA_ATTR_RESOURCE_TYPE}]`); } -jest.mock('../../../lib/components/internal/hooks/use-visual-mode', () => ({ - useVisualRefresh: jest.fn().mockReturnValue(false), -})); - -describe('Classic design', () => { - beforeEach(() => { - jest.mocked(useVisualRefresh).mockReturnValue(false); - }); - - test('should render normal layout by default', () => { - const { wrapper, container } = renderComponent(); - expect(wrapper).toBeTruthy(); - expect(getElementsText(getResourceTypeElements(container))).toEqual(['Resource']); - expect(getElementsText(getFunnelNameElements(container))).toEqual(['Page name']); - }); -}); - describe('Refresh design', () => { - beforeEach(() => { - jest.mocked(useVisualRefresh).mockReturnValue(true); - }); - test('should render normal layout by default', () => { const { wrapper, container } = renderComponent(); expect(wrapper).toBeTruthy(); diff --git a/src/button-dropdown/internal.tsx b/src/button-dropdown/internal.tsx index f84d170d2d..47daf65994 100644 --- a/src/button-dropdown/internal.tsx +++ b/src/button-dropdown/internal.tsx @@ -15,7 +15,6 @@ import Dropdown from '../internal/components/dropdown'; import OptionsList from '../internal/components/options-list'; import { useMobile } from '../internal/hooks/use-mobile'; import { useUniqueId } from '../internal/hooks/use-unique-id'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode/index.js'; import { isDevelopment } from '../internal/is-development'; import { spinWhenOpen } from '../internal/styles/motion/utils'; import { checkSafeUrl } from '../internal/utils/check-safe-url'; @@ -74,7 +73,6 @@ const InternalButtonDropdown = React.forwardRef( } } const isMainAction = mainAction && (variant === 'primary' || variant === 'normal'); - const isVisualRefresh = useVisualRefresh(); const { isOpen, @@ -236,7 +234,7 @@ const InternalButtonDropdown = React.forwardRef( className={clsx( styles['trigger-button'], hasNoText && styles['has-no-text'], - isVisualRefresh && styles['visual-refresh'], + styles['visual-refresh'], canBeFullWidth && styles['main-action-full-width'] )} variant={variant} @@ -275,7 +273,7 @@ const InternalButtonDropdown = React.forwardRef( className={clsx( styles['trigger-item'], styles['dropdown-trigger'], - isVisualRefresh && styles['visual-refresh'], + styles['visual-refresh'], styles[`variant-${variant}`], baseTriggerProps.disabled && styles.disabled, baseTriggerProps.loading && styles.loading diff --git a/src/cards/index.tsx b/src/cards/index.tsx index 015b80fd91..b59b59f277 100644 --- a/src/cards/index.tsx +++ b/src/cards/index.tsx @@ -15,7 +15,6 @@ import useBaseComponent from '../internal/hooks/use-base-component'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; import { useMobile } from '../internal/hooks/use-mobile'; import useMouseDownTarget from '../internal/hooks/use-mouse-down-target'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; import { applyDisplayName } from '../internal/utils/apply-display-name'; import InternalLiveRegion from '../live-region/internal'; import InternalStatusIndicator from '../status-indicator/internal'; @@ -71,10 +70,9 @@ const Cards = React.forwardRef(function ( metadata: { usesVisibleSections: !!visibleSections }, }); const baseProps = getBaseProps(rest); - const isRefresh = useVisualRefresh(); const isMobile = useMobile(); - const computedVariant = isRefresh ? variant : 'container'; + const computedVariant = variant; const headerIdRef = useRef(undefined); const setHeaderRef = useCallback((id: string) => { @@ -149,11 +147,7 @@ const Cards = React.forwardRef(function ( header={ hasToolsHeader && (
@@ -174,7 +168,7 @@ const Cards = React.forwardRef(function (
@@ -238,7 +232,6 @@ const CardsList = ({ }) => { const selectable = !!selectionType; const canClickEntireCard = selectable && entireCardClickable; - const isRefresh = useVisualRefresh(); const { moveFocusDown, moveFocusUp } = useSelectionFocusMove(selectionType, items.length); @@ -277,7 +270,7 @@ const CardsList = ({ role={listItemRole} >
{ diff --git a/src/cards/styles.scss b/src/cards/styles.scss index b2075f281b..95f5519d4c 100644 --- a/src/cards/styles.scss +++ b/src/cards/styles.scss @@ -36,9 +36,6 @@ border-end-start-radius: awsui.$border-radius-container; border-end-end-radius: awsui.$border-radius-container; } - &:not(.refresh)::after { - box-shadow: awsui.$shadow-container; - } &.refresh::after { border-block: solid awsui.$border-divider-section-width awsui.$color-border-divider-default; border-inline: solid awsui.$border-divider-section-width awsui.$color-border-divider-default; diff --git a/src/code-editor/index.tsx b/src/code-editor/index.tsx index 5155fa6499..fb5da79294 100644 --- a/src/code-editor/index.tsx +++ b/src/code-editor/index.tsx @@ -16,7 +16,6 @@ import useBaseComponent from '../internal/hooks/use-base-component'; import { useControllable } from '../internal/hooks/use-controllable'; import { useMergeRefs } from '../internal/hooks/use-merge-refs'; import { useUniqueId } from '../internal/hooks/use-unique-id'; -import { useVisualRefresh } from '../internal/hooks/use-visual-mode'; import { KeyCode } from '../internal/keycode'; import { applyDisplayName } from '../internal/utils/apply-display-name'; import InternalLiveRegion from '../live-region/internal'; @@ -69,7 +68,6 @@ const CodeEditor = forwardRef((props: CodeEditorProps, ref: React.Ref {loading && ( @@ -224,7 +222,7 @@ const CodeEditor = forwardRef((props: CodeEditorProps, ref: React.Ref
; warningsTabRef?: React.RefObject; @@ -50,7 +49,6 @@ export function StatusBar({ i18nStrings, errorCount, warningCount, - isRefresh, }: StatusBarProps) { const i18n = useInternalI18n('code-editor'); const errorText = `${i18n('i18nStrings.errorsTab', i18nStrings?.errorsTab)}: ${errorCount}`; @@ -83,7 +81,6 @@ export function StatusBar({ ref={errorsTabRef} ariaLabel={errorText} paneId={paneId} - isRefresh={isRefresh} /> @@ -104,7 +101,6 @@ export function StatusBar({ ariaHidden={paneStatus === 'error' && isTabFocused ? true : undefined} ariaLabel={warningText} paneId={paneId} - isRefresh={isRefresh} />