Skip to content

Commit 696473b

Browse files
[Scrollable] Add imperative handle to Scrollable Component to allow programmatic scrolling (#8555)
### WHY are these changes introduced? Fixes #7627 Related to https://github.com/Shopify/businesses/issues/1684 The Settings Modal in web is currently using a custom scrolling container as it needs to Scroll back to the top of the page on navigation. This is causing issues with popovers inside Settings as they don't find a Scrollable parent. This PR will allow us to switch to a Scrollable in the settings modal without losing the ability to re-scroll on navigation. ### WHAT is this pull request doing? By making `Scrollable` a `forwardRef` component we can expose an [imperative handle](https://stackoverflow.com/questions/62210286/declare-type-with-react-useimperativehandle) allowing a parent component to programmatically execute `scrollTo`. #### Impact: It was necessary to remove `Scrollable.ScrollTo` and `Scrollable.forNode` from the Scrollable class and export them separately as the ForwardRef component is now strongly typed. These are both _very_ lightly used in web, so it shouldn't be a terribly involved update. ### How to 🎩 🖥 [Local development instructions](https://github.com/Shopify/polaris/blob/main/README.md#local-development) 🗒 [General tophatting guidelines](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md) 📄 [Changelog guidelines](https://github.com/Shopify/polaris/blob/main/.github/CONTRIBUTING.md#changelog) Create a `Scrollable` and provide a `ref`. Add some buttons that will fire `ref.current?.scrollTo`. Scroll, then press a button and see that it scrolls back to the correct location. <details> <summary>Copy-paste this code in <code>playground/Playground.tsx</code>:</summary> ```jsx import React, {useEffect, useState} from 'react'; import {Scrollable, Page, Button, Stack, ScrollableRef} from '../src'; export function Playground() { const [page, setPage] = useState('1'); const ref = React.useRef<ScrollableRef>(null); useEffect(()=>{ ref.current?.scrollTo(0, {behavior: 'instant'}); }, [page]) return ( <Page title="Playground"> <Stack wrap={false} spacing="loose"> <Stack vertical> <Button onClick={() => setPage('1')}>Page 1</Button> <Button onClick={() => setPage('2')}>Page 2</Button> <Button onClick={() => setPage('3')}>Page 3</Button> </Stack> <Scrollable shadow style={{height: '100px'}} ref={ref} > <div style={{paddingTop:"1px"}}> <h3>Page {page}</h3> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor condimentum eleifend. Sed mollis non ante eget rutrum. Donec tincidunt luctus ipsum sed finibus. Praesent sapien quam, fringilla sit amet arcu ut, aliquam ullamcorper dui. Vivamus aliquet, felis sed viverra suscipit, tellus sapien imperdiet nibh, a dictum ante velit ac dolor. Aenean pharetra arcu at augue euismod efficitur. Fusce eleifend nisi quis enim gravida, ut condimentum tellus accumsan. Proin laoreet eu nisi sit amet pulvinar. Praesent id velit mauris. Phasellus egestas aliquet elementum. Vivamus sit amet dignissim lorem, et facilisis ligula. </p> <p> Proin consectetur mauris quis venenatis pretium. Integer lobortis nisi ac dolor aliquet varius. Sed nec dignissim tellus, eget suscipit diam. Integer non justo vel neque convallis dignissim. Nullam turpis velit, tincidunt sit amet tortor vel, rhoncus cursus dui. Curabitur vitae magna pulvinar, sodales nisl id, molestie ipsum. Pellentesque dignissim, nibh sed dapibus rutrum, leo odio consequat odio, at efficitur nulla sapien eget ligula. Vivamus elementum metus quis volutpat mattis. Pellentesque vestibulum, nulla a viverra bibendum, tortor risus euismod nisl, vitae hendrerit mi eros sit amet nisi. </p> <p> In quis vestibulum nunc. Nulla pellentesque nulla sit amet tortor vulputate bibendum. Fusce pretium leo sit amet dolor volutpat scelerisque. Aliquam fermentum risus quam, sit amet convallis mi lacinia in. Phasellus dui risus, consectetur ut vulputate non, laoreet id urna. Mauris sagittis ipsum et elit sollicitudin, et commodo ex eleifend. Pellentesque hendrerit lacinia egestas. Quisque posuere neque libero, ut pulvinar diam tincidunt quis. Donec nec arcu efficitur, sollicitudin elit a, rhoncus purus. Vestibulum laoreet ex et viverra viverra. Sed a quam ultrices, congue tortor ut, cursus ligula. </p> <p> In faucibus, est sed condimentum ultrices, massa orci tempor mi, sed eleifend justo massa ac est. Donec ullamcorper malesuada urna in ultricies. Aliquam augue felis, vulputate ut enim eget, luctus tristique diam. Nam imperdiet velit turpis, vitae semper felis accumsan nec. Nam sit amet erat tempor, luctus erat vel, finibus elit. Ut vulputate eu ligula nec lacinia. Pellentesque ullamcorper elit eget pharetra accumsan. Suspendisse in erat ac nulla fringilla posuere porttitor id ligula. Curabitur non magna lectus. Nulla facilisi. </p> <p> Aliquam facilisis, mi sit amet volutpat sagittis, elit nunc pulvinar ligula, sit amet consequat purus massa sit amet lectus. Etiam euismod pellentesque pharetra. Nullam et blandit libero, ut suscipit est. Phasellus sit amet rhoncus enim. Sed laoreet risus lectus, sed suscipit lorem dignissim feugiat. In dui justo, semper quis metus id, ornare tristique tortor. Sed non quam non metus gravida molestie. </p> </div> </Scrollable> </Stack> </Page> ); } ``` </details> ### 🎩 checklist - [ ] Tested on [mobile](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting.md#cross-browser-testing) - [ ] Tested on [multiple browsers](https://help.shopify.com/en/manual/shopify-admin/supported-browsers) - [ ] Tested for [accessibility](https://github.com/Shopify/polaris/blob/main/documentation/Accessibility%20testing.md) - [ ] Updated the component's `README.md` with documentation changes - [ ] [Tophatted documentation](https://github.com/Shopify/polaris/blob/main/documentation/Tophatting%20documentation.md) changes in the style guide --------- Co-authored-by: Sam Rose <[email protected]> Co-authored-by: Sam Rose <[email protected]>
1 parent 1a36ed6 commit 696473b

File tree

4 files changed

+746
-101
lines changed

4 files changed

+746
-101
lines changed

.changeset/beige-seas-cough.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/polaris': minor
3+
---
4+
5+
Added a forward `ref` to permit programmatic scrolling for `Scrollable` (example: `scrollRef.current?.scrollTo(0)`)

0 commit comments

Comments
 (0)