Skip to content

Commit

Permalink
[components] Add portal components
Browse files Browse the repository at this point in the history
  • Loading branch information
mariuslundgard authored and rexxars committed Oct 6, 2020
1 parent 000f2f8 commit 2f13f6c
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 0 deletions.
8 changes: 8 additions & 0 deletions packages/@sanity/components/sanity.json
Original file line number Diff line number Diff line change
Expand Up @@ -1100,6 +1100,14 @@
{
"implements": "part:@sanity/components/tabs/tab-panel",
"path": "tabs/TabPanel.js"
},
{
"implements": "part:@sanity/components/portal",
"path": "portal"
},
{
"implements": "part:@sanity/base/component",
"path": "portal/story"
}
]
}
7 changes: 7 additions & 0 deletions packages/@sanity/components/src/portal/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {createContext} from 'react'

export interface PortalContextInterface {
element: HTMLElement
}

export const PortalContext = createContext(null)
12 changes: 12 additions & 0 deletions packages/@sanity/components/src/portal/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {useContext} from 'react'
import {PortalContext} from './context'

export function usePortal() {
const portal = useContext(PortalContext)

if (!portal) {
throw new Error('missing portal in context')
}

return portal
}
3 changes: 3 additions & 0 deletions packages/@sanity/components/src/portal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './hooks'
export * from './portal'
export * from './provider'
14 changes: 14 additions & 0 deletions packages/@sanity/components/src/portal/portal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ReactDOM from 'react-dom'
import {usePortal} from './hooks'

interface PortalProps {
children: React.ReactNode
}

export function Portal(props: PortalProps) {
const portal = usePortal()

if (!portal.element) return null

return ReactDOM.createPortal(props.children, portal.element)
}
15 changes: 15 additions & 0 deletions packages/@sanity/components/src/portal/provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import {PortalContext} from './context'

interface PortalProviderProps {
children: React.ReactNode
element: HTMLElement
}

export function PortalProvider(props: PortalProviderProps) {
return (
<PortalContext.Provider value={{element: props.element}}>
{props.children}
</PortalContext.Provider>
)
}
2 changes: 2 additions & 0 deletions packages/@sanity/components/src/portal/stories/default.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.root {
}
47 changes: 47 additions & 0 deletions packages/@sanity/components/src/portal/stories/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {Portal, PortalProvider} from 'part:@sanity/components/portal'
import Sanity from 'part:@sanity/storybook/addons/sanity'
import React, {useRef, useEffect} from 'react'

export function DefaultStory() {
return (
<Sanity part="part:@sanity/components/dialogs/default" propTables={[Portal]}>
<PortalExample />
</Sanity>
)
}

function PortalExample() {
const rootRef = useRef(null)
const portalRef = useRef(document.createElement('div'))

useEffect(() => {
rootRef.current.appendChild(portalRef.current)
return () => {
rootRef.current.removeChild(portalRef.current)
}
}, [])

return (
<PortalProvider element={portalRef.current}>
<div ref={rootRef}>Portal demo:</div>

<Portal>
<div
style={{
background: 'rgba(255, 0, 0, 0.1)',
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<div style={{background: '#fff', padding: 20}}>Hello from portal</div>
</div>
</Portal>
</PortalProvider>
)
}
7 changes: 7 additions & 0 deletions packages/@sanity/components/src/portal/story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {storiesOf} from 'part:@sanity/storybook'
import {withKnobs} from 'part:@sanity/storybook/addons/knobs'
import {DefaultStory} from './stories/default'

storiesOf('@sanity/components/portal', module)
.addDecorator(withKnobs)
.add('Default', DefaultStory)

0 comments on commit 2f13f6c

Please sign in to comment.