Skip to content

Commit

Permalink
arrow button slide in and out behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
broccolinisoup committed Oct 10, 2022
1 parent dec0552 commit e7bc17b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/UnderlineNav2/UnderlineNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const handleArrowBtnsVisibility = (
const scrollOffsets = {scrollLeft, scrollRight}
callback(scrollOffsets)
}

const overflowEffect = (
navWidth: number,
moreMenuWidth: number,
Expand Down Expand Up @@ -361,6 +362,7 @@ export const UnderlineNav = forwardRef(
>
{isCoarsePointer && (
<ArrowButton
scrollValue={scrollValues.scrollLeft}
type="left"
show={scrollValues.scrollLeft > 0}
onScrollWithButton={onScrollWithButton}
Expand Down Expand Up @@ -413,6 +415,7 @@ export const UnderlineNav = forwardRef(

{isCoarsePointer && (
<ArrowButton
scrollValue={scrollValues.scrollRight}
type="right"
show={scrollValues.scrollRight > 0}
onScrollWithButton={onScrollWithButton}
Expand Down
23 changes: 20 additions & 3 deletions src/UnderlineNav2/UnderlineNavArrowButton.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, {useContext} from 'react'
import {IconButton} from '../Button/IconButton'
import {ChevronLeftIcon, ChevronRightIcon} from '@primer/octicons-react'
import {btnWrapperStyles, getArrowBtnStyles, getArrowHiddenBtn} from './styles'
import {btnWrapperStyles, getArrowBtnStyles} from './styles'
import {OnScrollWithButtonEventType} from './types'
import {UnderlineNavContext} from './UnderlineNavContext'
import Box from '../Box'

const ArrowButton = ({
scrollValue,
type,
show,
onScrollWithButton,
'aria-label': ariaLabel
}: {
scrollValue: number
type: 'left' | 'right'
show: boolean
onScrollWithButton: OnScrollWithButtonEventType
Expand All @@ -21,6 +23,8 @@ const ArrowButton = ({
const rightBtnRef = React.useRef<HTMLButtonElement>(null)
const {theme} = useContext(UnderlineNavContext)
const direction = type === 'left' ? -1 : 1
const ARROW_BTN_WIDTH = 44 // Min touch target size is 44px

// re-trigger focus on the button with aria-disabled=true when it becomes hidden to communicate to screen readers that the button is no longer available
React.useEffect(() => {
const currentBtn = type === 'left' ? leftBtnRef.current : rightBtnRef.current
Expand All @@ -31,15 +35,28 @@ const ArrowButton = ({
currentBtn?.blur()
}
}, [show, type])

let translateX = 0
let display = 'flex'

// Determine the translateX value to transform for the slide in/out effect
if (scrollValue === 0) {
// If the scrollValue is 0, the buttons should be hidden
translateX = ARROW_BTN_WIDTH * direction
// This is mainly needed for the right arrow button. Because hiding translateX value for it is positive (44px) and this positive value was causing button to be visibly overflowed rathan than hiding.
display = 'none'
} else if (scrollValue <= ARROW_BTN_WIDTH) translateX = (ARROW_BTN_WIDTH - scrollValue) * direction
else translateX = 0

return (
<Box sx={btnWrapperStyles(theme, type, show)}>
<Box sx={btnWrapperStyles(theme, type, show, translateX, display)}>
<IconButton
tabIndex={show ? 0 : -1}
ref={type === 'left' ? leftBtnRef : rightBtnRef}
aria-label={`Scroll ${ariaLabel} navigation ${type}`}
onClick={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => onScrollWithButton(e, direction)}
icon={type === 'left' ? ChevronLeftIcon : ChevronRightIcon}
sx={show ? getArrowBtnStyles(theme, type) : getArrowHiddenBtn(theme, type)}
sx={getArrowBtnStyles(theme, type)}
aria-disabled={!show}
/>
</Box>
Expand Down
23 changes: 11 additions & 12 deletions src/UnderlineNav2/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,25 @@ export const moreBtnStyles = {
paddingX: 2
}

export const btnWrapperStyles = (theme?: Theme, direction = 'left', show = false) => ({
export const btnWrapperStyles = (
theme?: Theme,
direction = 'left',
show = false,
translateX = 0,
display = 'flex'
) => ({
position: 'absolute',
zIndex: 1,
top: 0,
bottom: 0,
left: direction === 'left' ? 0 : 'auto',
right: direction === 'right' ? 0 : 'auto',
display: 'flex',
alignItems: 'center',
background: show
? `linear-gradient(to ${direction} ,#fff0, ${theme?.colors.canvas.default} 14px, ${theme?.colors.canvas.default} 100%)`
: 'transparent'
: 'transparent',
transform: `translateX(${translateX}px)`,
display: `${display}`
})

export const getArrowBtnStyles = (theme?: Theme, direction = 'left') => ({
Expand All @@ -89,14 +96,11 @@ export const getArrowBtnStyles = (theme?: Theme, direction = 'left') => ({
margin: 0,
border: 0,
borderRadius: 2,
paddingX: '6px',
paddingX: '14px',
paddingY: 0,
background: 'transparent',
height: '60%',

opacity: 1,
transition: 'opacity 250ms ease-out',

'&:hover:not([disabled]), &:focus-visible': {
background: theme?.colors.canvas.default
},
Expand All @@ -116,11 +120,6 @@ export const getArrowBtnStyles = (theme?: Theme, direction = 'left') => ({
}
})

export const getArrowHiddenBtn = (theme?: Theme, direction = 'left') => ({
...getArrowBtnStyles(theme, direction),
opacity: 0
})

export const getLinkStyles = (
theme?: Theme,
props?: Partial<Pick<UnderlineNavProps, 'variant'>>,
Expand Down

0 comments on commit e7bc17b

Please sign in to comment.