Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Render Visual Refresh background height in sync with content #1331

Merged
merged 57 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
04df79d
Fix: Prevent app layout background and table from rendering out of sync
jperals Jul 13, 2023
f7234e2
refactor: Merge custom container query sync hook into useDynamicOverlap
jperals Jul 13, 2023
a5a705b
Use queueMicrotask and flushSync inside useDynamicOverlap hook
jperals Jul 13, 2023
64179d5
Refactor
jperals Jul 13, 2023
efd419e
Do not use queueMicrotask
jperals Jul 13, 2023
87aea84
Restore ResizeObserver hook
jperals Jul 13, 2023
323bf6e
fix: Remove problematic type annotation
jperals Jul 13, 2023
e04950d
Revert "Do not use queueMicrotask"
jperals Jul 13, 2023
4829a91
Do state updates synchronously only in useEffect and not in UseLayout…
jperals Jul 13, 2023
f1cd56a
Add comment
jperals Jul 14, 2023
d247a03
Update dynamic overlap imperatively
jperals Jul 14, 2023
8b4aebc
Restore Resize Observer hook
jperals Jul 13, 2023
82efcef
Revert "chore: Configure coverage thresholds in Jest (#1310)"
jperals Jul 14, 2023
054c66f
chore: Improve density in VR components (#1318)
jkuelz Jul 12, 2023
cc3329d
chore: bump semver from 6.3.0 to 6.3.1 in /.github/workflows/bundle-s…
dependabot[bot] Jul 13, 2023
c5a4966
fix: Unshare funnel hooks properties (#1304)
connorlanigan Jul 13, 2023
b04acd5
chore: Add unit tests for analytics (#1296)
connorlanigan Jul 13, 2023
411f2c8
chore: bump stylelint from 14.16.0 to 15.10.1 (#1300)
dependabot[bot] Jul 13, 2023
25f007a
fix: Use appropriate aria-haspopup for select/multiselect with filter…
gethinwebster Jul 13, 2023
b9cbf12
feat: Move filteringAriaLabel and filteringPlaceholder in property fi…
avinashbot Jul 13, 2023
859e30f
feat: Move i18nStrings.submitText in wizard to top level (#1314)
avinashbot Jul 13, 2023
3660271
feat: Move i18nStrings.removeButtonAriaLabel in attribute editor to t…
avinashbot Jul 13, 2023
a6f4985
feat: Move xTickFormatter, yTickFormatter, and detailTotalFormatter i…
avinashbot Jul 13, 2023
41dc5d3
feat: Move i18nStrings.inContextInputPlaceholder in s3 resource selec…
avinashbot Jul 13, 2023
8156a2d
chore: Reduce button horizontal padding in VR compact mode (#1306)
jkuelz Jul 13, 2023
a1512cd
fix: Nested containers should not create a new subStep context (#1322)
connorlanigan Jul 14, 2023
8deb19b
fix: Only add aria-controls when dropdown is open (#1327)
gethinwebster Jul 14, 2023
676c45d
fix: Emit funnelSubStepStart event when a form element is focused asy…
connorlanigan Jul 14, 2023
0c40286
chore: Improve info density of headers and containers in VR (#1317)
jkuelz Jul 14, 2023
b26733b
chore: Rerun conflicting snapshot tests from before the merge (#1334)
jkuelz Jul 14, 2023
4066d64
chore: Update VR typography heading sizes and weight (#1321)
jkuelz Jul 15, 2023
23cddba
chore: Update VR spacing design token descriptions (#1335)
jkuelz Jul 15, 2023
f9e9a92
feat: Add fit-height property to charts (#1273)
pan-kot Jul 16, 2023
7eded5e
chore: Remove core-js and qs dependencies (#1336)
just-boris Jul 17, 2023
489608c
fix: Move inline-editor success icon to focus state (#1264)
johannes-weber Jul 17, 2023
5e9f003
Add test
jperals Jul 17, 2023
c21efd3
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 17, 2023
9ce6e26
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 17, 2023
e80138a
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 19, 2023
97d2baf
Revert "Revert "chore: Configure coverage thresholds in Jest (#1310)""
jperals Jul 19, 2023
cca23f2
Add comment
jperals Jul 19, 2023
1c5ee2b
Change function call order for clarity
jperals Jul 19, 2023
bb15330
Add test page
jperals Jul 19, 2023
d531559
Let table header be h1
jperals Jul 19, 2023
67e426a
Fine tune test page
jperals Jul 20, 2023
df6471c
Remove dynamicOverlapHeight from state, handle it exclusively in the DOM
jperals Jul 20, 2023
95b72c5
Update app layout context test
jperals Jul 20, 2023
9482d66
Initialize isDynamicOverlapDisabled to true
jperals Jul 20, 2023
53e0848
Fix file name
jperals Jul 20, 2023
908294e
Improve tests
jperals Jul 24, 2023
7079c82
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 24, 2023
688c29c
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 25, 2023
fe96a65
Add test for state update on re-rendering
jperals Jul 26, 2023
dfe14a6
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 26, 2023
cf26752
Merge branch 'main' into fix/dynamic-overlap-sync
jperals Jul 27, 2023
9a79533
Refactor dependency array to prevent unnecessary calls
jperals Jul 27, 2023
0bc9b7e
Refactor retrieving layoutElement as RefObject
jperals Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';
import AppLayout from '~components/app-layout';
import labels from './utils/labels';
import Table from '~components/table';
import { generateItems, Instance } from '../table/generate-data';
import { columnsConfig } from '../table/shared-configs';
import ExpandableSection from '~components/expandable-section';
import Header from '~components/header';

const items = generateItems(20);

export default function () {
return (
<AppLayout
ariaLabels={labels}
contentType="table"
navigationHide={true}
content={
<Table<Instance>
header={
<>
<Header variant="awsui-h1-sticky">Header that changes size when scrolling</Header>
<ExpandableSection headerText="Click to expand header area">
<div style={{ height: '300px' }}>Content</div>
</ExpandableSection>
</>
}
stickyHeader={true}
variant="full-page"
columnDefinitions={columnsConfig}
items={items}
/>
}
/>
);
}
106 changes: 106 additions & 0 deletions src/app-layout/__tests__/dynamic-overlap.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React from 'react';
import { render, screen } from '@testing-library/react';
import AppLayout, { AppLayoutProps } from '../../../lib/components/app-layout';
import { useDynamicOverlap } from '../../../lib/components/internal/hooks/use-dynamic-overlap';
import { useAppLayoutInternals } from '../../../lib/components/app-layout/visual-refresh/context';

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;

jest.mock('../../../lib/components/internal/hooks/container-queries/utils', () => ({
...jest.requireActual('../../../lib/components/internal/hooks/container-queries/utils'),
convertResizeObserverEntry: () => ({ contentBoxHeight: positiveHeight ? 800 : 0 }),
}));

describe('Dynamic overlap', () => {
function ComponentWithDynamicOverlap() {
const ref = useDynamicOverlap();
const { isDynamicOverlapSet, isDynamicOverlapDisabled } = useAppLayoutInternals();
return (
<>
<div ref={ref} />
<div data-testid="is-dynamic-overlap-set">{isDynamicOverlapSet.toString()}</div>
<div data-testid="is-dynamic-overlap-disabled">{isDynamicOverlapDisabled.toString()}</div>
</>
);
}

function ComponentWithoutDynamicOverlap() {
const { isDynamicOverlapSet, isDynamicOverlapDisabled } = useAppLayoutInternals();
return (
<>
<div data-testid="is-dynamic-overlap-set">{isDynamicOverlapSet.toString()}</div>
<div data-testid="is-dynamic-overlap-disabled">{isDynamicOverlapDisabled.toString()}</div>
</>
);
}

function renderApp(appLayoutProps?: AppLayoutProps) {
const { rerender } = render(<AppLayout {...appLayoutProps} />);
return {
isDynamicOverlapSet: () => screen.getByTestId('is-dynamic-overlap-set').textContent,
isDynamicOverlapDisabled: () => screen.getByTestId('is-dynamic-overlap-disabled').textContent,
rerender: (appLayoutProps?: AppLayoutProps) => rerender(<AppLayout {...appLayoutProps} />),
};
}

beforeEach(() => {
positiveHeight = true;
});

test('sets dynamic overlap when content header is present', () => {
const { isDynamicOverlapSet, isDynamicOverlapDisabled } = renderApp({
content: <ComponentWithDynamicOverlap />,
contentHeader: 'Content header',
});
expect(isDynamicOverlapSet()).toBe('true');
expect(isDynamicOverlapDisabled()).toBe('false');
});

test('sets dynamic overlap when height is higher than 0', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we have a test case where the height dynamically changes (for example, from 800 to 0) and we check for the expected values of isDynamicOverlapSet and isDynamicOverlapDisabled?

Or is this not something that can happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's not impossible that these state variables change during the lifecycle of an application but I think it should be rather rare. Some of these events should happen:

  1. The height of a child component that uses the dynamic overlap hook changes from 0 to non-0, or the other way around from non-0 to 0
  2. A child component that uses the dynamic overlap hook is added or removed
  3. contentHeader is passed and then not passed anymore, or the other way around
  4. The value of the disableDynamicOverlap property passed to the app layout changes

I just added a test that checks these state variables after re-rendering, based on the case 2 above. Case 1 would be tricky to test because we would need to simulate a call to the resize observer hook.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alright, that makes sense!

const { isDynamicOverlapSet, isDynamicOverlapDisabled } = renderApp({ content: <ComponentWithDynamicOverlap /> });
expect(isDynamicOverlapSet()).toBe('true');
expect(isDynamicOverlapDisabled()).toBe('false');
});

test('does not set dynamic overlap when no content header is present and height is 0', () => {
positiveHeight = false;
const { isDynamicOverlapSet, isDynamicOverlapDisabled } = renderApp({ content: <ComponentWithDynamicOverlap /> });
expect(isDynamicOverlapSet()).toBe('false');
expect(isDynamicOverlapDisabled()).toBe('true');
});

test('does not set dynamic overlap when the useDynamicOverlap hook is not used', () => {
const { isDynamicOverlapSet, isDynamicOverlapDisabled } = renderApp({
content: <ComponentWithoutDynamicOverlap />,
disableContentHeaderOverlap: true,
});
expect(isDynamicOverlapSet()).toBe('false');
expect(isDynamicOverlapDisabled()).toBe('true');
});

test('disables dynamic overlap when explicitly specified in the app layout props', () => {
const { isDynamicOverlapDisabled } = renderApp({
content: <ComponentWithDynamicOverlap />,
disableContentHeaderOverlap: true,
});
expect(isDynamicOverlapDisabled()).toBe('true');
});

test('updates state accordingly when re-rendering', () => {
const { isDynamicOverlapSet, isDynamicOverlapDisabled, rerender } = renderApp({
content: <ComponentWithDynamicOverlap />,
});
expect(isDynamicOverlapSet()).toBe('true');
expect(isDynamicOverlapDisabled()).toBe('false');
rerender({ content: <ComponentWithoutDynamicOverlap /> });
expect(isDynamicOverlapSet()).toBe('false');
expect(isDynamicOverlapDisabled()).toBe('true');
});
});
5 changes: 2 additions & 3 deletions src/app-layout/visual-refresh/background.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import styles from './styles.css.js';
export default function Background() {
const {
breadcrumbs,
contentHeader,
dynamicOverlapHeight,
isDynamicOverlapSet,
hasNotificationsContent,
hasStickyBackground,
isMobile,
stickyNotifications,
} = useAppLayoutInternals();

if (!hasNotificationsContent && (!breadcrumbs || isMobile) && !contentHeader && dynamicOverlapHeight <= 0) {
if (!hasNotificationsContent && (!breadcrumbs || isMobile) && !isDynamicOverlapSet) {
return null;
}

Expand Down
44 changes: 40 additions & 4 deletions src/app-layout/visual-refresh/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { warnOnce } from '@cloudscape-design/component-toolkit/internal';
import useResize from '../utils/use-resize';
import styles from './styles.css.js';
import { useContainerQuery } from '@cloudscape-design/component-toolkit';
import customCssProps from '../../internal/generated/custom-css-properties';

interface AppLayoutInternals extends AppLayoutProps {
activeDrawerId?: string | null;
Expand All @@ -40,7 +41,6 @@ interface AppLayoutInternals extends AppLayoutProps {
drawerRef: React.Ref<HTMLElement>;
resizeHandle: React.ReactElement;
drawersTriggerCount: number;
dynamicOverlapHeight: number;
handleDrawersClick: (activeDrawerId: string | null, skipFocusControl?: boolean) => void;
handleSplitPanelClick: () => void;
handleNavigationClick: (isOpen: boolean) => void;
Expand All @@ -52,6 +52,8 @@ interface AppLayoutInternals extends AppLayoutProps {
hasNotificationsContent: boolean;
hasOpenDrawer?: boolean;
hasStickyBackground: boolean;
isDynamicOverlapDisabled: boolean;
isDynamicOverlapSet: boolean;
isMobile: boolean;
isNavigationOpen: boolean;
isSplitPanelForcedPosition: boolean;
Expand Down Expand Up @@ -136,7 +138,8 @@ export const AppLayoutInternalsProvider = React.forwardRef(
* If a child component utilizes a sticky header the hasStickyBackground property will determine
* if the background remains in the same vertical position.
*/
const [dynamicOverlapHeight, setDynamicOverlapHeight] = useState(0);
const [isDynamicOverlapSet, setIsDynamicOverlapSet] = useState(false);
const [isDynamicOverlapDisabled, setIsDynamicOverlapDisabled] = useState(true);
const [hasStickyBackground, setHasStickyBackground] = useState(false);

/**
Expand Down Expand Up @@ -487,6 +490,38 @@ export const AppLayoutInternalsProvider = React.forwardRef(
const mainElement = useRef<HTMLDivElement>(null);
const [mainOffsetLeft, setMainOffsetLeft] = useState(0);

const updateDynamicOverlapHeight = useCallback(
(height: number) => {
/**
* The disableContentHeaderOverlap property is absolute and will always disable the overlap
* if it is set to true. If there is no contentHeader then the overlap should be disabled
* unless there is a dynamicOverlapHeight. The dynamicOverlapHeight property is set by a
* component in the content slot that needs to manually control the overlap height.
*/
const isOverlapSet = !!props.contentHeader || height > 0;
const isOverlapDisabled = props.disableContentHeaderOverlap || !isOverlapSet;
setIsDynamicOverlapSet(isOverlapSet);
setIsDynamicOverlapDisabled(isOverlapDisabled);

/**
* React 18 will trigger a paint before the state is correctly updated
* (see https://github.com/facebook/react/issues/24331).
* To work around this, we bypass React state updates and imperatively update the custom property on the DOM.
* An alternative would be to use `queueMicrotask` and `flushSync` in the ResizeObserver callback,
* but that would have some performance impact as it would delay the render.
* Using React state for `isDynamicOverlapSet` and `isDynamicOverlapDisabled` is less problematic
* because they will rarely change within the lifecycle of an application.
*/
const element = typeof layoutElement === 'function' ? layoutElement(null) : layoutElement?.current;
Copy link
Member

Choose a reason for hiding this comment

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

Not sure what layoutElement(null) does here. It just unsets the ref? I think it works here just because of internal implementation details, since layoutElement happens to be an ObjectRef usually. If we're using the ref for things other than resize observer, maybe another ref property (typed as ObjectRef) is needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

This variable is returned by useContainerQuery which returns React.Ref<any>, which in turn is RefCallback<any> | RefObject<any> | null, but its value is set only by the Layout component here so we know it's going to be an ObjectRef and not a RefCallback.

If it looks better, we could as well just do nothing if it is a function.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated.

Copy link
Member

Choose a reason for hiding this comment

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

Not ideal, but it does have a comment and it works for now. Not going to treat it as blocking.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should layoutElement somehow end up being used as a RefCallback, it will also cause this useCallback to recreate the updateDynamicOverlapHeight function on every render.

Anyway, it seems unlikely, so it is also non-blocking for me.

if (isOverlapDisabled || height <= 0) {
element?.style.removeProperty(customCssProps.overlapHeight);
} else {
element?.style.setProperty(customCssProps.overlapHeight, `${height}px`);
}
},
[layoutElement, props.contentHeader, props.disableContentHeaderOverlap]
Copy link
Member

Choose a reason for hiding this comment

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

props.contentHeader is a ReactNode, which is rarely stable between renders anyway. This means the function will update identity each render, making useCallback useless.

If it's just provided to check for the existence of the property rather than the contents, maybe you could define a variable outside the function and use it internally? That would make it safer.

const hasContentHeader = !!props.contentHeader;
useCallback(() => { ... }, [layoutElement, hasContentHeader, props.disableContentHeaderOverlap]);

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated as per your suggestion.

);

useLayoutEffect(
function handleMainOffsetLeft() {
setMainOffsetLeft(mainElement?.current?.offsetLeft ?? 0);
Expand Down Expand Up @@ -600,7 +635,6 @@ export const AppLayoutInternalsProvider = React.forwardRef(
drawerRef,
resizeHandle,
drawersTriggerCount,
dynamicOverlapHeight,
headerHeight,
footerHeight,
hasDefaultToolsWidth,
Expand All @@ -616,6 +650,8 @@ export const AppLayoutInternalsProvider = React.forwardRef(
hasStickyBackground,
isMobile,
isNavigationOpen: isNavigationOpen ?? false,
isDynamicOverlapDisabled,
isDynamicOverlapSet,
isSplitPanelForcedPosition,
isSplitPanelOpen,
isToolsOpen,
Expand Down Expand Up @@ -660,7 +696,7 @@ export const AppLayoutInternalsProvider = React.forwardRef(
setHasStickyBackground,
}}
>
<DynamicOverlapContext.Provider value={setDynamicOverlapHeight}>{children}</DynamicOverlapContext.Provider>
<DynamicOverlapContext.Provider value={updateDynamicOverlapHeight}>{children}</DynamicOverlapContext.Provider>
</AppLayoutContext.Provider>
</AppLayoutInternalsContext.Provider>
);
Expand Down
19 changes: 4 additions & 15 deletions src/app-layout/visual-refresh/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ export default function Layout({ children }: LayoutProps) {
contentHeader,
contentType,
disableBodyScroll,
disableContentHeaderOverlap,
disableContentPaddings,
drawersTriggerCount,
dynamicOverlapHeight,
footerHeight,
hasNotificationsContent,
hasStickyBackground,
hasOpenDrawer,
headerHeight,
isDynamicOverlapDisabled,
isMobile,
isNavigationOpen,
layoutElement,
Expand All @@ -53,14 +52,6 @@ export default function Layout({ children }: LayoutProps) {
const hasContentGapLeft = isNavigationOpen || navigationHide;
const hasContentGapRight = drawersTriggerCount <= 0 || hasOpenDrawer;

/**
* The disableContentHeaderOverlap property is absolute and will always disable the overlap
* if it is set to true. If there is no contentHeader then the overlap should be disabled
* unless there is a dynamicOverlapHeight. The dynamicOverlapHeight property is set by a
* component in the content slot that needs to manually control the overlap height.
*/
const isOverlapDisabled = disableContentHeaderOverlap || (!contentHeader && dynamicOverlapHeight <= 0);

return (
<main
className={clsx(
Expand All @@ -80,7 +71,7 @@ export default function Layout({ children }: LayoutProps) {
[styles['has-split-panel']]: splitPanelDisplayed,
[styles['has-sticky-background']]: hasStickyBackground,
[styles['has-sticky-notifications']]: stickyNotifications && hasNotificationsContent,
[styles['is-overlap-disabled']]: isOverlapDisabled,
[styles['is-overlap-disabled']]: isDynamicOverlapDisabled,
},
testutilStyles.root
)}
Expand All @@ -93,8 +84,6 @@ export default function Layout({ children }: LayoutProps) {
...(maxContentWidth && { [customCssProps.maxContentWidth]: `${maxContentWidth}px` }),
...(minContentWidth && { [customCssProps.minContentWidth]: `${minContentWidth}px` }),
[customCssProps.notificationsHeight]: `${notificationsHeight}px`,
...(!isOverlapDisabled &&
dynamicOverlapHeight > 0 && { [customCssProps.overlapHeight]: `${dynamicOverlapHeight}px` }),
}}
>
{children}
Expand All @@ -104,8 +93,8 @@ export default function Layout({ children }: LayoutProps) {

/*
The Notifications, Breadcrumbs, Header, and Main are all rendered in the center
column of the grid layout. Any of these could be the first child to render in the
content area if the previous siblings do not exist. The grid gap before the first
column of the grid layout. Any of these could be the first child to render in the
content area if the previous siblings do not exist. The grid gap before the first
child will be different to ensure vertical alignment with the trigger buttons.
*/
function getContentFirstChild(
Expand Down
11 changes: 1 addition & 10 deletions src/internal/hooks/container-queries/use-resize-observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ResizeObserver, ResizeObserverEntry } from '@juggle/resize-observer';
import React, { useEffect, useLayoutEffect } from 'react';
import { useStableEventHandler } from '../use-stable-event-handler';
import { ContainerQueryEntry } from '@cloudscape-design/component-toolkit';
import { convertResizeObserverEntry } from './utils';

type ElementReference = (() => Element | null) | React.RefObject<Element>;

Expand Down Expand Up @@ -58,13 +59,3 @@ export function useResizeObserver(elementRef: ElementReference, onObserve: (entr
}
}, [elementRef, stableOnObserve]);
}

function convertResizeObserverEntry(entry: ResizeObserverEntry): ContainerQueryEntry {
return {
target: entry.target,
contentBoxWidth: entry.contentBoxSize[0].inlineSize,
contentBoxHeight: entry.contentBoxSize[0].blockSize,
borderBoxWidth: entry.borderBoxSize[0].inlineSize,
borderBoxHeight: entry.borderBoxSize[0].blockSize,
};
}
14 changes: 14 additions & 0 deletions src/internal/hooks/container-queries/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { ResizeObserverEntry } from '@juggle/resize-observer';
import { ContainerQueryEntry } from '@cloudscape-design/component-toolkit';

export function convertResizeObserverEntry(entry: ResizeObserverEntry): ContainerQueryEntry {
return {
target: entry.target,
contentBoxWidth: entry.contentBoxSize[0].inlineSize,
contentBoxHeight: entry.contentBoxSize[0].blockSize,
borderBoxWidth: entry.borderBoxSize[0].inlineSize,
borderBoxHeight: entry.borderBoxSize[0].blockSize,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { render, screen } from '@testing-library/react';
import { useDynamicOverlap } from '../../../../../lib/components/internal/hooks/use-dynamic-overlap';
import { DynamicOverlapContext } from '../../../../../lib/components/internal/context/dynamic-overlap-context';

jest.mock('@cloudscape-design/component-toolkit', () => ({
...jest.requireActual('@cloudscape-design/component-toolkit'),
useContainerQuery: () => [800, () => {}],
jest.mock('../../../../../lib/components/internal/hooks/container-queries/utils', () => ({
...jest.requireActual('../../../../../lib/components/internal/hooks/container-queries/utils'),
convertResizeObserverEntry: () => ({ contentBoxHeight: 800 }),
}));

function renderApp(children: React.ReactNode) {
Expand Down
Loading
Loading