Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "fix(react-drawer): allow 1px tolerance in scroll-bottom detection so the footer divider hides at >100% zoom",
"packageName": "@fluentui/react-drawer",
"email": "adam.znamenacek@eway-crm.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { DrawerBody } from './DrawerBody';
import { getScrollState } from './useDrawerBody';
import { isConformant } from '../../testing/isConformant';

describe('DrawerBody', () => {
Expand All @@ -21,4 +22,66 @@ describe('DrawerBody', () => {
</div>
`);
});

describe('getScrollState', () => {
it('returns none when content does not overflow', () => {
const state = getScrollState({
scrollTop: 0,
scrollHeight: 100,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('none');
});

it('returns top when at the start of scrollable content', () => {
const state = getScrollState({
scrollTop: 0,
scrollHeight: 200,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('top');
});

it('returns middle when between top and bottom', () => {
const state = getScrollState({
scrollTop: 50,
scrollHeight: 200,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('middle');
});

it('returns bottom when at the end of scrollable content', () => {
const state = getScrollState({
scrollTop: 100,
scrollHeight: 200,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('bottom');
});

it('returns bottom when within 1px tolerance at the end', () => {
const state = getScrollState({
scrollTop: 89.4,
scrollHeight: 190,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('bottom');
});

it('returns middle when more than 1px away from the end', () => {
const state = getScrollState({
scrollTop: 88.9,
scrollHeight: 190,
clientHeight: 100,
} as HTMLElement);

expect(state).toBe('middle');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ import type { DrawerScrollState } from '../../shared/DrawerBase.types';
import type { DrawerBodyProps, DrawerBodyState } from './DrawerBody.types';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';

/**
* Treat values within 1px of the scroll height as "bottom" to account for
* fractional scroll measurements caused by browser zoom and display scaling.
*/
const SCROLL_BOTTOM_TOLERANCE = 1;

/**
* Get the current scroll state of the DrawerBody.
*
* @internal
* @param element - HTMLElement to check scroll state of
*/
const getScrollState = ({ scrollTop, scrollHeight, clientHeight }: HTMLElement): DrawerScrollState => {
export const getScrollState = ({ scrollTop, scrollHeight, clientHeight }: HTMLElement): DrawerScrollState => {
if (scrollHeight <= clientHeight) {
return 'none';
}
Expand All @@ -31,7 +37,9 @@ const getScrollState = ({ scrollTop, scrollHeight, clientHeight }: HTMLElement):
return 'top';
}

if (scrollTop + clientHeight === scrollHeight) {
const distanceFromBottom = scrollHeight - (scrollTop + clientHeight);

if (distanceFromBottom <= SCROLL_BOTTOM_TOLERANCE) {
return 'bottom';
}

Expand Down