Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import createWrapper from '../../../lib/components/test-utils/selectors';
import { viewports } from './constants';
import { getUrlParams, testIf, Theme } from './utils';

import splitPanelTestUtilStyles from '../../../lib/components/split-panel/test-classes/styles.selectors.js';

const wrapper = createWrapper().findAppLayout();

interface SetupTestObj {
Expand Down Expand Up @@ -59,7 +61,11 @@ describe.each(['classic', 'refresh', 'refresh-toolbar'] as const)('%s', theme =>
await page.keys(['Tab', 'Tab']);
await expect(page.isFocused(wrapper.findSplitPanel().findCloseButton().toSelector())).resolves.toBe(true);
await page.keys('Enter');
await expect(page.isFocused(wrapper.findSplitPanel().findOpenButton().toSelector())).resolves.toBe(true);
const openButton =
mobile || theme === 'refresh-toolbar'
? wrapper.findSplitPanel().findByClassName(splitPanelTestUtilStyles['open-button'])
: wrapper.findSplitPanelOpenButton();
await expect(page.isFocused(openButton.toSelector())).resolves.toBe(true);
await page.keys('Enter');
await expect(page.isFocused(wrapper.findSplitPanel().findSlider().toSelector())).resolves.toBe(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ describe('refresh-toolbar', () => {
const tooltipSelector = wrapper.findDrawerTriggerTooltip().toSelector();
const expectedTooltipText = 'Open panel';

const assertSplitPanelTriggerFocusedWithTooltip = async (page: AppLayoutDrawersPage) => {
await expect(page.isFocused(splitPanelTriggerSelector)).resolves.toBe(true);
await expect(page.getText(tooltipSelector)).resolves.toBe(expectedTooltipText);
await expect(page.getElementsCount(tooltipSelector)).resolves.toBe(1);
};

describe.each(['bottom', 'side'] as const)('splitPanelPosition=%s', splitPanelPosition => {
test(
'Shows tooltip correctly on split panel trigger for mouse interactions',
Expand Down Expand Up @@ -57,24 +63,21 @@ describe('refresh-toolbar', () => {
);

test(
'Shows tooltip correctly for split panel trigger for keyboard (tab) interactions',
'Shows and hides tooltip correctly for split panel trigger for keyboard (tab) interactions',
setupTest({ theme, size, splitPanelPosition }, async (page: AppLayoutDrawersPage) => {
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The path taken by these tests to focus the split panel trigger in the toolbar was not working anymore because it was assuming that the focus stays on the trigger after clicking it, but now it moves to the split panel.

await page.click(splitPanelTriggerSelector);

await expect(page.isFocused(wrapper.findSplitPanel().findSlider().toSelector())).resolves.toBeTruthy();
// Focus split panel trigger
await page.click(wrapper.findToolbar().toSelector());
await page.keys(['Tab', 'Tab']);
await page.isFocused(wrapper.findSplitPanel().findCloseButton().toSelector());
await page.keys('Enter');
await assertSplitPanelTriggerFocusedWithTooltip(page);
// Focus breadcrumbs
await page.keys(['Shift', 'Tab']);
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
//navigate away from slide panel
await page.keys(['Shift', 'Tab', 'Null']); // to last breadcrumb - be aware if breadcrumb has tooltip
//navigate back to drawer trigger
// Navigate back to split panel trigger
await page.keys(['Tab']);
await expect(page.isFocused(splitPanelTriggerSelector)).resolves.toBeTruthy();
await await expect(page.getText(tooltipSelector)).resolves.toBe(expectedTooltipText);
await expect(page.getElementsCount(tooltipSelector)).resolves.toBe(1);
await page.keys(['Shift', 'Tab', 'Null']);
await assertSplitPanelTriggerFocusedWithTooltip(page);
// Open the split panel
await page.keys('Enter');
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
})
);
Expand All @@ -83,19 +86,10 @@ describe('refresh-toolbar', () => {
'Removes tooltip from split panel trigger on escape key press after showing from keyboard event',
setupTest({ theme, size, splitPanelPosition }, async (page: AppLayoutDrawersPage) => {
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
await page.click(splitPanelTriggerSelector);
await expect(page.isFocused(wrapper.findSplitPanel().findSlider().toSelector())).resolves.toBeTruthy();
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
await page.click(splitPanelTriggerSelector);
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
//navigate away from slide panel
await page.keys(['Shift', 'Tab', 'Null']); // to last breadcrumb - be aware if breadcrumb has tooltip
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
//navigate back to drawer trigger
await page.keys(['Tab']);
await expect(page.isFocused(splitPanelTriggerSelector)).resolves.toBeTruthy();
await expect(page.getText(tooltipSelector)).resolves.toBe(expectedTooltipText);
await expect(page.getElementsCount(tooltipSelector)).resolves.toBe(1);
// Focus split panel trigger
await page.click(wrapper.findToolbar().toSelector());
await page.keys(['Tab', 'Tab']);
await assertSplitPanelTriggerFocusedWithTooltip(page);
await page.keys('Escape');
await expect(page.isExisting(tooltipSelector)).resolves.toBe(false);
})
Expand Down
8 changes: 7 additions & 1 deletion src/app-layout/__tests__/split-panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { describeEachAppLayout, renderComponent, splitPanelI18nStrings } from '.
import applayoutTools from '../../../lib/components/app-layout/visual-refresh/styles.selectors.js';
import { AppLayoutWrapper } from '../../../lib/components/test-utils/dom';

import testUtilStyles from '../../../lib/components/split-panel/test-classes/styles.selectors.js';

const defaultSplitPanel = (
<SplitPanel i18nStrings={splitPanelI18nStrings} header="test header">
test content
Expand Down Expand Up @@ -135,7 +137,11 @@ describeEachAppLayout({ sizes: ['desktop'] }, ({ theme }) => {
);
wrapper.findSplitPanelOpenButton()!.click();
wrapper.findSplitPanel()!.findCloseButton()!.click();
expect(wrapper.findSplitPanelOpenButton()!.getElement()).toHaveFocus();
const button =
position === 'side'
? wrapper.findSplitPanelOpenButton()
: wrapper.findSplitPanel()!.findByClassName(testUtilStyles['open-button']);
expect(button!.getElement()).toHaveFocus();
});

test(`Moves focus to the slider when focusSplitPanel() is called`, () => {
Expand Down
4 changes: 2 additions & 2 deletions src/app-layout/__tests__/widget-compatibility.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ test('renders visual refresh toolbar with navigation using legacy props', () =>
expect(onNavigationToggle).toHaveBeenCalled();
});

test('renders visual refresh toolbar with split panel using toolbarProps', () => {
test('renders visual refresh toolbar with split panel trigger using toolbarProps', () => {
const onSplitPanelToggle = jest.fn();
renderNewAppLayout({ toolbarProps: { onSplitPanelToggle } });
wrapper.findByClassName(splitPanelTestUtilStyles['open-button'])!.click();
expect(onSplitPanelToggle).toHaveBeenCalled();
});

test('renders visual refresh toolbar with split panel using legacy props', () => {
test('renders visual refresh toolbar with split panel trigger using legacy props', () => {
const onSplitPanelToggle = jest.fn();
renderLegacyAppLayout({ appLayoutInternals: { onSplitPanelToggle } });
wrapper.findByClassName(splitPanelTestUtilStyles['open-button'])!.click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export function DrawerTriggers({
const toolsOnlyMode = drawers.length === 1 && drawers[0].id === TOOLS_DRAWER_ID;
const globalDrawersStartIndex = drawers.length;
const hasOpenDrawer = !!activeDrawerId || (splitPanelPosition === 'side' && splitPanelOpen);
const splitPanelResolvedPosition = splitPanelToggleProps?.position;

return (
<aside
Expand Down Expand Up @@ -137,10 +138,10 @@ export function DrawerTriggers({
testutilStyles['drawers-trigger'],
splitPanelTestUtilStyles['open-button']
)}
iconName={splitPanelToggleProps.position === 'side' ? 'view-vertical' : 'view-horizontal'}
iconName={splitPanelResolvedPosition === 'side' ? 'view-vertical' : 'view-horizontal'}
onClick={() => onSplitPanelToggle?.()}
selected={splitPanelToggleProps.active}
ref={splitPanelFocusRef}
ref={splitPanelResolvedPosition === 'side' ? splitPanelFocusRef : undefined}
hasTooltip={true}
isMobile={isMobile}
isForSplitPanel={true}
Expand Down
3 changes: 3 additions & 0 deletions src/internal/generated/styles/tokens.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ export const spaceScaledS: string;

// Line height
export const lineHeightBodyM: string;

// Border thickness
export const borderPanelTopWidth: string;
18 changes: 15 additions & 3 deletions src/split-panel/bottom.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import clsx from 'clsx';

import { useResizeObserver } from '@cloudscape-design/component-toolkit/internal';

import { useAppLayoutToolbarEnabled } from '../app-layout/utils/feature-flags';
import { useSplitPanelContext } from '../internal/context/split-panel-context';
import * as tokens from '../internal/generated/styles/tokens';
import { useMobile } from '../internal/hooks/use-mobile';
import { useVisualRefresh } from '../internal/hooks/use-visual-mode';
import { SplitPanelContentProps } from './interfaces';
Expand Down Expand Up @@ -45,7 +46,14 @@ export function SplitPanelContentBottom({
const isMobile = useMobile();

const headerRef = useRef<HTMLDivElement>(null);
useResizeObserver(headerRef, entry => reportHeaderHeight(entry.borderBoxHeight));
const [headerBlockSize, setHeaderBlockSize] = useState<number>();

useResizeObserver(headerRef, entry => {
const { borderBoxHeight } = entry;
setHeaderBlockSize(borderBoxHeight);
reportHeaderHeight(borderBoxHeight);
});

useEffect(() => {
// report empty height when unmounting the panel
return () => reportHeaderHeight(0);
Expand Down Expand Up @@ -75,7 +83,11 @@ export function SplitPanelContentBottom({
insetBlockEnd: bottomOffset,
insetInlineStart: leftOffset,
insetInlineEnd: rightOffset,
blockSize: isOpen ? cappedSize : isToolbar ? '0px' : undefined,
blockSize: isOpen
? cappedSize
: isToolbar && headerBlockSize !== undefined
? `calc(${headerBlockSize}px + ${tokens.borderPanelTopWidth})`
: undefined,
}}
ref={splitPanelRef}
>
Expand Down
2 changes: 1 addition & 1 deletion src/split-panel/implementation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function SplitPanelImplementation({
ariaLabel={i18nStrings.closeButtonAriaLabel}
ariaExpanded={isOpen}
/>
) : isToolbar || position === 'side' ? null : (
) : position === 'side' ? null : (
<InternalButton
className={testUtilStyles['open-button']}
iconName="angle-up"
Expand Down
5 changes: 0 additions & 5 deletions src/split-panel/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,6 @@ $app-layout-drawer-width: calc(#{awsui.$space-layout-toggle-diameter} + 2 * #{aw
}
&.drawer-closed {
overflow: hidden;
&.with-toolbar {
block-size: 0px;
border-block: none;
border-inline: none;
}
}
&.drawer-closed:hover {
background: awsui.$color-background-layout-panel-hover;
Expand Down
Loading