Skip to content

Commit

Permalink
feat(Popup): new prop closeOnScroll close popup when scroll outside…
Browse files Browse the repository at this point in the history
… of it (#21453)

* close on scroll

* chglog

* e2e
  • Loading branch information
YuanboXue-Amber authored Jan 26, 2022
1 parent 096e9ba commit a8158d3
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 1 deletion.
3 changes: 3 additions & 0 deletions packages/fluentui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- `FocusTrapZone`: add handleRef method instead of function to prevent calling it on each re-render @annabratseiko ([#21337](https://github.com/microsoft/fluentui/pull/21337))
- Fix color slot titles in docsite @notandrew ([#21378](https://github.com/microsoft/fluentui/pull/21378))

### Features
- Add new Popup prop `closeOnScroll` to close popup when scroll happens outside of the popover element @yuanboxue-amber ([#21453](https://github.com/microsoft/fluentui/pull/21453))

<!--------------------------------[ v0.60.1 ]------------------------------- -->
## [v0.60.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-northstar_v0.60.1) (2022-01-17)
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-northstar_v0.60.0..@fluentui/react-northstar_v0.60.1)
Expand Down
52 changes: 52 additions & 0 deletions packages/fluentui/e2e/tests/popupDismissScroll-example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import { Button, Popup, Flex } from '@fluentui/react-northstar';

export const selectors = {
simplePopup: {
triggerId: 'trigger',
contentId: 'content',
},
contextPopup: {
triggerId: 'trigger-context',
contentId: 'content-context',
},
dismissScrollPopup: {
triggerId: 'trigger-dismiss',
contentId: 'content-dismiss',
},
};

const PopupClickHandlingExample = () => {
return (
<Flex column>
simple popup
<Popup
trigger={<Button id={selectors.simplePopup.triggerId} content="Open Popup" />}
content={{
content: 'Open a popup',
id: selectors.simplePopup.contentId,
}}
/>
popup open on context
<Popup
trigger={<Button id={selectors.contextPopup.triggerId} content="Open Popup" />}
content={{
content: 'Open a popup',
id: selectors.contextPopup.contentId,
}}
on="context"
/>
popup with closeOnScroll
<Popup
trigger={<Button id={selectors.dismissScrollPopup.triggerId} content="Open Popup" />}
content={{
content: 'Open a popup',
id: selectors.dismissScrollPopup.contentId,
}}
closeOnScroll
/>
</Flex>
);
};

export default PopupClickHandlingExample;
28 changes: 28 additions & 0 deletions packages/fluentui/e2e/tests/popupDismissScroll.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { selectors } from './popupDismissScroll-example';

describe('Popup - dismiss on scroll container', () => {
beforeEach(() => {
cy.gotoTestCase(__filename, `#${selectors.simplePopup.triggerId}`);
});

it('simple popup does not dismiss content on scroll', () => {
cy.clickOn(`#${selectors.simplePopup.triggerId}`); // opens popup
cy.visible(`#${selectors.simplePopup.contentId}`); // popup visible
cy.get('body').trigger('wheel'); // page scroll
cy.visible(`#${selectors.simplePopup.contentId}`); // popup still visible
});

it('popup on context dismiss content on scroll', () => {
cy.get(`#${selectors.contextPopup.triggerId}`).rightclick(); // opens popup
cy.visible(`#${selectors.contextPopup.contentId}`); // popup visible
cy.get('body').trigger('wheel'); // page scroll
cy.notExist(`#${selectors.contextPopup.contentId}`); // popup dismissed
});

it('popup with closeOnScroll prop dismiss content on scroll', () => {
cy.clickOn(`#${selectors.dismissScrollPopup.triggerId}`); // opens popup
cy.visible(`#${selectors.dismissScrollPopup.contentId}`); // popup visible
cy.get('body').trigger('wheel'); // page scroll
cy.notExist(`#${selectors.dismissScrollPopup.contentId}`); // popup dismissed
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export interface PopupProps

/** Controls whether or not auto focus should be applied, using boolean or AutoFocusZoneProps type value. */
autoFocus?: boolean | AutoFocusZoneProps;

/** Close the popup when scroll happens outside of Popup */
closeOnScroll?: boolean;
}

export const popupClassName = 'ui-popup';
Expand Down Expand Up @@ -170,6 +173,7 @@ export const Popup: React.FC<PopupProps> &
unstable_disableTether,
unstable_pinned,
autoSize,
closeOnScroll,
} = props;

const [open, setOpen] = useAutoControlled({
Expand Down Expand Up @@ -477,7 +481,7 @@ export const Popup: React.FC<PopupProps> &
capture
/>

{isOpenedByRightClick && (
{(isOpenedByRightClick || closeOnScroll) && (
<>
<EventListener listener={dismissOnScroll} target={context.target} type="wheel" capture />
<EventListener listener={dismissOnScroll} target={context.target} type="touchmove" capture />
Expand Down Expand Up @@ -685,6 +689,7 @@ Popup.propTypes = {
contentRef: customPropTypes.ref,
trapFocus: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
autoFocus: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
closeOnScroll: PropTypes.bool,
};
Popup.defaultProps = {
accessibility: popupBehavior,
Expand Down

0 comments on commit a8158d3

Please sign in to comment.