Skip to content

Commit

Permalink
[base, desk-tool, etc] Add scroll container for emulating scroll even…
Browse files Browse the repository at this point in the history
…t bubbling
  • Loading branch information
bjoerge authored and rexxars committed Oct 6, 2020
1 parent fd47139 commit 29686ce
Show file tree
Hide file tree
Showing 16 changed files with 92 additions and 84 deletions.
1 change: 1 addition & 0 deletions packages/@sanity/base/ScrollContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './lib/components/ScrollContainer'
70 changes: 70 additions & 0 deletions packages/@sanity/base/src/components/ScrollContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react'

type ScrollEventHandler = (event: Event) => void
interface ScrollContextValue {
onScroll?: ScrollEventHandler
}

export const Context = React.createContext<ScrollContextValue>({})

export function ScrollMonitor({
onScroll,
children
}: {
onScroll: ScrollEventHandler
children?: React.ReactNode
}) {
const parentContext = React.useContext(Context)
const handleScroll = React.useCallback(
(event: Event) => {
onScroll(event)
if (parentContext.onScroll) {
parentContext.onScroll(event)
}
},
[parentContext, onScroll]
)

return <Context.Provider value={{onScroll: handleScroll}}>{children}</Context.Provider>
}

/**
* This provides a utility function for use within Sanity Studios to create scrollable containers
* Note: this is used by different studio utilities to track positions of elements on screen
* Note: It will call any given `onScroll` callback with a Native DOM Event, and not a React Synthetic event
* Note: It will not make sure the element is actually scrollable, this still needs to be done with css as usual
*/
export function ScrollContainer<T extends React.ElementType = 'div'>({
onScroll,
as = 'div',
...props
}: React.ComponentProps<T> & {
onScroll?: ScrollEventHandler
as?: T
}) {
const containerRef = React.useRef<HTMLDivElement>(null)
const parentContext = React.useContext(Context)

const handleScroll = React.useCallback(
(event: Event) => {
if (onScroll) {
onScroll(event)
}
if (parentContext.onScroll) {
parentContext.onScroll(event)
}
},
[onScroll]
)

React.useEffect(() => {
containerRef.current!.addEventListener('scroll', handleScroll, {
passive: true
})
return () => {
containerRef.current!.removeEventListener('scroll', handleScroll)
}
}, [onScroll])

return React.createElement(as, {ref: containerRef, ...props})
}
4 changes: 0 additions & 4 deletions packages/@sanity/components/sanity.json
Original file line number Diff line number Diff line change
Expand Up @@ -941,10 +941,6 @@
"implements": "part:@sanity/components/panes/split-pane-wrapper",
"path": "panes/SplitPaneWrapper"
},
{
"implements": "part:@sanity/components/utilities/scroll-container",
"path": "utilities/ScrollContainer"
},
{
"implements": "part:@sanity/components/typography/hotkeys",
"path": "typography/Hotkeys"
Expand Down
2 changes: 2 additions & 0 deletions packages/@sanity/components/src/dialogs/DefaultDialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
}

.card {
position: relative;
composes: shadow-24dp from 'part:@sanity/base/theme/shadows-style';
border-radius: var(--dialog-border-radius);
animation-name: reveal;
Expand Down Expand Up @@ -184,6 +185,7 @@

.content {
composes: scrollY from 'part:@sanity/base/theme/layout/scrolling-style';
position: relative;
border-radius: var(--dialog-border-radius) var(--dialog-border-radius) 0 0;
background-color: var(--component-bg);
color: var(--component-text-color);
Expand Down
5 changes: 3 additions & 2 deletions packages/@sanity/components/src/dialogs/DefaultDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Escapable from '../utilities/Escapable'
import Stacked from '../utilities/Stacked'
import {DefaultDialogActions} from './DefaultDialogActions'
import {DialogAction, DialogColor} from './types'
import {ScrollContainer} from '@sanity/base/ScrollContainer'

interface DefaultDialogProps {
actions?: DialogAction[]
Expand Down Expand Up @@ -125,9 +126,9 @@ function DefaultDialog(props: DefaultDialogProps) {
</div>
)}

<div className={contentClassName}>
<ScrollContainer className={contentClassName}>
<div className={styles.contentWrapper}>{children}</div>
</div>
</ScrollContainer>

{actions && actions.length > 0 && (
<div className={styles.footer}>
Expand Down
5 changes: 4 additions & 1 deletion packages/@sanity/components/src/dialogs/FullscreenDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ButtonGrid from 'part:@sanity/components/buttons/button-grid'
import styles from 'part:@sanity/components/dialogs/fullscreen-style'
import {Portal} from 'part:@sanity/components/portal'
import React from 'react'
import {ScrollContainer} from '@sanity/base/ScrollContainer'
import StackedEscapable from '../utilities/StackedEscapable'
import {DialogAction} from './types'

Expand Down Expand Up @@ -92,7 +93,9 @@ export default class FullScreenDialog extends React.PureComponent<FullScreenDial
</header>
)}

{this.props.children && <div className={styles.content}>{this.props.children}</div>}
{this.props.children && (
<ScrollContainer className={styles.content}>{this.props.children}</ScrollContainer>
)}

{actions && actions.length > 0 && (
<div className={styles.actionsWrapper}>{this.renderActions(actions)}</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/@sanity/components/src/panes/DefaultPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {IntentLink} from 'part:@sanity/base/router'
import Button from 'part:@sanity/components/buttons/default'
import IntentButton from 'part:@sanity/components/buttons/intent'
import TabPanel from 'part:@sanity/components/tabs/tab-panel'
import ScrollContainer from 'part:@sanity/components/utilities/scroll-container'
import {ScrollContainer} from '@sanity/base/ScrollContainer'
import React from 'react'
import {childrenToElementArray} from '../helpers'
import Styleable from '../utilities/Styleable'
Expand Down
4 changes: 0 additions & 4 deletions packages/@sanity/components/src/utilities/ScrollContainer.css

This file was deleted.

64 changes: 0 additions & 64 deletions packages/@sanity/components/src/utilities/ScrollContainer.tsx

This file was deleted.

1 change: 0 additions & 1 deletion packages/@sanity/components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
"part:@sanity/components/utilities/image-loader": ["./utilities/ImageLoader"],
"part:@sanity/components/utilities/poppable": ["./utilities/Poppable"],
"part:@sanity/components/utilities/portal": ["./utilities/Portal"],
"part:@sanity/components/utilities/scroll-container": ["./utilities/ScrollContainer"],
"part:@sanity/components/utilities/stacked": ["./utilities/Stacked"],
"part:@sanity/components/utilities/stacked-escapable": ["./utilities/StackEscapable"],
"part:@sanity/components/validation/list": ["./validation/ValidationList"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@
min-height: 0;
padding: var(--large-padding) var(--medium-padding);
overflow: auto;
position: relative;
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,14 @@ export function ChangesPanel({
)}
</div>
</header>

<div className={styles.body}>
<ScrollContainer className={styles.body}>
<Content
diff={diff}
documentContext={documentContext}
loading={loading}
schemaType={schemaType}
/>
</div>
</ScrollContainer>
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

.documentScroller {
height: 100%;
position: relative;

@media (--screen-medium) {
height: 100%;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {DocumentHeaderTitle} from './header/title'
import {DocumentPanelHeader} from './header/header'
import {getMenuItems} from './menuItems'
import {FormView} from './views'
import {ScrollContainer} from '@sanity/base/ScrollContainer'

import styles from './documentPanel.css'
import {
Expand Down Expand Up @@ -152,7 +153,7 @@ export function DocumentPanel(props: DocumentPanelProps) {

<PortalProvider element={portalElement}>
<div className={styles.documentViewerContainer}>
<div className={styles.documentScroller}>
<ScrollContainer className={styles.documentScroller}>
{activeView.type === 'form' && (
<FormView
id={props.documentId}
Expand Down Expand Up @@ -180,7 +181,7 @@ export function DocumentPanel(props: DocumentPanelProps) {
options: activeView.options,
schemaType: props.schemaType
})}
</div>
</ScrollContainer>

<div className={styles.portal} ref={portalRef} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
OnCopyFn,
PortableTextEditor
} from '@sanity/portable-text-editor'
import {ScrollContainer} from '@sanity/base/ScrollContainer'
import PatchEvent from '../../PatchEvent'
import {Marker} from '../../typedefs'
import styles from './PortableTextInput.css'
Expand Down Expand Up @@ -164,7 +165,7 @@ function PortableTextSanityEditor(props: Props) {
/>
</div>
</div>
<div className={scClassNames}>
<ScrollContainer className={scClassNames}>
<div className={editorWrapperClassNames}>
<div className={editorClassNames}>
<PortableTextEditable
Expand All @@ -182,7 +183,7 @@ function PortableTextSanityEditor(props: Props) {
</div>
<div className={styles.blockExtras}>{renderBlockExtras()}</div>
</div>
</div>
</ScrollContainer>
</div>
),
[initialSelection, isFullscreen, value, markers, readOnly]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
overflow-y: overlay;
flex-direction: column;
flex-grow: 1;
position: relative;

@nest .fullscreenPortal & {
min-height: 0;
Expand Down

0 comments on commit 29686ce

Please sign in to comment.