Skip to content

Commit

Permalink
🎨 introduct floating ui instead of two separate packages (#2106)
Browse files Browse the repository at this point in the history
  • Loading branch information
BorghildSelle authored Feb 16, 2024
1 parent a1d9b41 commit 6b1675f
Show file tree
Hide file tree
Showing 6 changed files with 415 additions and 2,178 deletions.
3 changes: 1 addition & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@equinor/eds-core-react": "0.33.0",
"@equinor/eds-icons": "^0.19.1",
"@equinor/eds-tokens": "^0.9.0",
"@floating-ui/react": "^0.26.9",
"@next/bundle-analyzer": "^12.1.0",
"@portabletext/react": "^3.0.0",
"@portabletext/to-html": "^2.0.5",
Expand Down Expand Up @@ -67,13 +68,11 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^3.1.4",
"react-focus-lock": "^2.9.2",
"react-hook-form": "7.45.2",
"react-instantsearch": "^7.3.0",
"react-instantsearch-router-nextjs": "^7.3.0",
"react-intl": "^6.0.2",
"react-is": "^18.1.0",
"react-remove-scroll": "^2.5.5",
"react-twitter-embed": "^4.0.4",
"sharp": "^0.32.6",
"styled-components": "^5.3.9",
Expand Down
48 changes: 32 additions & 16 deletions web/pageComponents/shared/siteMenu/SiteMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useEffect, useCallback, useState } from 'react'
import styled from 'styled-components'
import { useFloating, useInteractions, useDismiss, FloatingOverlay, FloatingFocusManager } from '@floating-ui/react'
import { useRouter } from 'next/router'
import { RemoveScroll } from 'react-remove-scroll'
import FocusLock from 'react-focus-lock'
import { Menu, MenuButton, Link } from '@components'
import { MenuGroup } from './MenuGroup'
import { TopbarDropdown } from './TopbarDropdown'
Expand Down Expand Up @@ -47,6 +46,13 @@ const SiteMenu = ({ data, ...rest }: MenuProps) => {
const [isOpen, setIsOpen] = useState(false)
const intl = useIntl()

const { refs, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
})

const { getReferenceProps, getFloatingProps } = useInteractions([useDismiss(context)])

const handleRouteChange = useCallback(() => {
setIsOpen(false)
}, [])
Expand All @@ -57,24 +63,34 @@ const SiteMenu = ({ data, ...rest }: MenuProps) => {
return () => router.events.off('routeChangeComplete', handleRouteChange)
}, [router.events, handleRouteChange])

function onMenuButtonClick() {
setIsOpen(!isOpen)
}

const title = intl.formatMessage({ id: 'menu', defaultMessage: 'Menu' })
const allSitesURL = getAllSitesLink('internal', router?.locale || 'en')

return (
<>
<MenuButton title={title} aria-expanded={isOpen} onClick={onMenuButtonClick} {...rest} />
<FocusLock disabled={!isOpen} returnFocus>
<RemoveScroll enabled={isOpen}>
<TopbarDropdown isOpen={isOpen} className={RemoveScroll.classNames.zeroRight} background={'White'}>
{isOpen && (
<MenuButton
ref={refs.setReference}
title={title}
{...getReferenceProps()}
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-haspopup={true}
{...rest}
/>
{isOpen && (
<FloatingFocusManager context={context}>
<FloatingOverlay ref={refs.setFloating} lockScroll {...getFloatingProps()}>
<TopbarDropdown background={'White'}>
<nav>
<NavTopbar>
<LogoLink />
<MenuButton title={title} aria-expanded={true} expanded onClick={() => setIsOpen(false)}></MenuButton>
<MenuButton
title={title}
aria-haspopup={true}
aria-expanded={true}
expanded
onClick={() => setIsOpen(false)}
></MenuButton>
</NavTopbar>
<MenuContainer>
<Menu>
Expand All @@ -87,10 +103,10 @@ const SiteMenu = ({ data, ...rest }: MenuProps) => {
</AllSitesLink>
</MenuContainer>
</nav>
)}
</TopbarDropdown>
</RemoveScroll>
</FocusLock>
</TopbarDropdown>
</FloatingOverlay>
</FloatingFocusManager>
)}
</>
)
}
Expand Down
11 changes: 5 additions & 6 deletions web/pageComponents/shared/siteMenu/TopbarDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,23 @@ import styled from 'styled-components'
const StyledTopbarDropdown = styled(BackgroundContainer)`
position: fixed;
overflow: auto;
display: var(--display);
z-index: 50;
left: 0;
top: 0;
right: 0;
right: var(--right);
bottom: 0;
`
type Props = {
isOpen: boolean
right?: string
children: ReactNode
} & BackgroundContainerProps

export const TopbarDropdown = ({ isOpen, children, ...rest }: Props) => {
export const TopbarDropdown = ({ children, right = '15px', style, ...rest }: Props) => {
return (
<StyledTopbarDropdown
style={
{
'--display': isOpen ? 'block' : 'none',
...style,
'--right': right,
} as CSSProperties
}
{...rest}
Expand Down
94 changes: 55 additions & 39 deletions web/pageComponents/shared/siteMenu/simple/SimpleSiteMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import { useEffect, useCallback, useState } from 'react'
import styled from 'styled-components'
import { useRouter } from 'next/router'
import { RemoveScroll } from 'react-remove-scroll'
import FocusLock from 'react-focus-lock'
import { FormattedMessage, useIntl } from 'react-intl'
import { SimpleMenuWrapper } from './SimpleMenuWrapper'
import { MenuButton, Link } from '@components'
Expand All @@ -16,6 +14,7 @@ import type { SimpleMenuData, SimpleGroupData } from '../../../../types/types'
import { TopbarDropdown } from '../TopbarDropdown'
import { LogoLink } from '../../LogoLink'
import { NavTopbar } from '../NavTopbar'
import { FloatingFocusManager, FloatingOverlay, useDismiss, useFloating, useInteractions } from '@floating-ui/react'

const MenuContainer = styled.div`
font-size: var(--typeScale-1);
Expand Down Expand Up @@ -55,6 +54,13 @@ const SimpleSiteMenu = ({ data, ...rest }: MenuProps) => {
setIsOpen(false)
}, [])

const { refs, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
})

const { getReferenceProps, getFloatingProps } = useInteractions([useDismiss(context)])

useEffect(() => {
router.events.on('routeChangeComplete', handleRouteChange)
return () => router.events.off('routeChangeComplete', handleRouteChange)
Expand All @@ -69,44 +75,54 @@ const SimpleSiteMenu = ({ data, ...rest }: MenuProps) => {

return (
<>
<MenuButton title={title} aria-expanded={isOpen} onClick={onMenuButtonClick} {...rest} />
<FocusLock disabled={!isOpen} returnFocus>
<RemoveScroll enabled={isOpen}>
<TopbarDropdown isOpen={isOpen} className={RemoveScroll.classNames.zeroRight}>
<nav>
<NavTopbar>
<LogoLink />
<MenuButton title={title} aria-expanded={true} expanded onClick={() => setIsOpen(false)}></MenuButton>
</NavTopbar>
<MenuContainer>
<SimpleMenuWrapper>
{menuItems?.map((item: SimpleGroupData, idx: number) => {
if (item?.type === 'simpleMenuGroup') {
return <SimpleMenuItem item={item} key={item.id} index={idx} />
} else if (item?.type === 'simpleMenuLink') {
// Is this really necessary?
if (item.link && !item.link.slug) {
console.warn('Missing slug for simple menu link')
<MenuButton
ref={refs.setReference}
{...getReferenceProps()}
title={title}
aria-expanded={isOpen}
onClick={onMenuButtonClick}
aria-haspopup={true}
{...rest}
/>
{isOpen && (
<FloatingFocusManager context={context}>
<FloatingOverlay ref={refs.setFloating} lockScroll {...getFloatingProps()}>
<TopbarDropdown>
<nav>
<NavTopbar>
<LogoLink />
<MenuButton title={title} aria-expanded={true} expanded onClick={() => setIsOpen(false)}></MenuButton>
</NavTopbar>
<MenuContainer>
<SimpleMenuWrapper>
{menuItems?.map((item: SimpleGroupData, idx: number) => {
if (item?.type === 'simpleMenuGroup') {
return <SimpleMenuItem item={item} key={item.id} index={idx} />
} else if (item?.type === 'simpleMenuLink') {
// Is this really necessary?
if (item.link && !item.link.slug) {
console.warn('Missing slug for simple menu link')
}
return (
<li key={item.id}>
<MenuLink variant="contentLink" href={(item.link && item.link.slug) || '/'}>
{' '}
{item.label}{' '}
</MenuLink>
</li>
)
}
return (
<li key={item.id}>
<MenuLink variant="contentLink" href={(item.link && item.link.slug) || '/'}>
{' '}
{item.label}{' '}
</MenuLink>
</li>
)
}
})}
<AllSitesLink href={allSitesURL}>
<FormattedMessage id="all_sites" defaultMessage="All sites" />
</AllSitesLink>
</SimpleMenuWrapper>
</MenuContainer>
</nav>
</TopbarDropdown>
</RemoveScroll>
</FocusLock>
})}
<AllSitesLink href={allSitesURL}>
<FormattedMessage id="all_sites" defaultMessage="All sites" />
</AllSitesLink>
</SimpleMenuWrapper>
</MenuContainer>
</nav>
</TopbarDropdown>
</FloatingOverlay>
</FloatingFocusManager>
)}
</>
)
}
Expand Down
9 changes: 4 additions & 5 deletions web/pages/search/index.global.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import type { GetStaticProps } from 'next/types'
import { defaultLanguage } from '../../languages'
import { getIsoFromLocale } from '../../lib/localization'
import getIntl from '../../common/helpers/getIntl'

import { RemoveScroll } from 'react-remove-scroll'
import styled from 'styled-components'
import { Button } from '@components'
import { Icon } from '@equinor/eds-core-react'
Expand All @@ -16,6 +14,7 @@ import { NavTopbar } from '../../pageComponents/shared/siteMenu/NavTopbar'
import { LogoLink } from '../../pageComponents/shared/LogoLink'
import Search from '../../pageComponents/search/Search'
import { useRouter } from 'next/router'
import { FloatingOverlay } from '@floating-ui/react'

const InvertedButton = styled(Button)`
color: var(--white-100);
Expand Down Expand Up @@ -44,8 +43,8 @@ export default function SearchPage() {
return (
<>
<NextSeo title={searchTitle}></NextSeo>
<RemoveScroll enabled={true}>
<TopbarDropdown isOpen={true} background={'Slate Blue 95'}>
<FloatingOverlay lockScroll>
<TopbarDropdown background={'Slate Blue 95'}>
<NavTopbar>
<LogoLink />
<InvertedButton
Expand All @@ -63,7 +62,7 @@ export default function SearchPage() {
<Search />
</SearchContainer>
</TopbarDropdown>
</RemoveScroll>
</FloatingOverlay>
</>
)
}
Expand Down
Loading

0 comments on commit 6b1675f

Please sign in to comment.