Skip to content

Commit

Permalink
fix(tabs): add gradient visibility logic to handle tab overflow scena…
Browse files Browse the repository at this point in the history
…rios
  • Loading branch information
gitwoz committed Sep 2, 2024
1 parent 618c444 commit c2c1404
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
52 changes: 49 additions & 3 deletions src/components/SquareTabs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import classNames from 'classnames'
import { useEffect, useRef, useState } from 'react'

import styles from './styles.module.css'

Expand Down Expand Up @@ -34,15 +35,60 @@ interface SquareTabsProps {
export const SquareTabs: React.FC<React.PropsWithChildren<SquareTabsProps>> & {
Tab: typeof Tab
} = ({ children, sticky }) => {
const navRef = useRef<HTMLUListElement>(null)
const containerRef = useRef<HTMLElement>(null)
const $nav = navRef.current
const $container = containerRef.current
const [showLeftGradient, setShowLeftGradient] = useState(false)
const [showRightGradient, setShowRightGradient] = useState(false)

const isTabsOverflowing = () => {
if (!$nav || !$container) return false
return $nav.scrollWidth > $container.clientWidth
}

const calculateGradient = () => {
if (!$nav || !$container) return

const isAtLeftMost = $nav.scrollLeft <= 0
const isAtRightMost = $nav.scrollLeft + $nav.clientWidth >= $nav.scrollWidth

setShowLeftGradient(!isAtLeftMost)
setShowRightGradient(!isAtRightMost)
}

useEffect(() => {
if (!isTabsOverflowing() || !$nav) return

// initial gradient
calculateGradient()

$nav.addEventListener('scroll', calculateGradient)

return () => {
if (!$nav) return

$nav.removeEventListener('scroll', calculateGradient)
}
}, [$nav])

const containerClasses = classNames({
[styles.container]: true,
[styles.showLeftGradient]: showLeftGradient,
[styles.showRightGradient]: showRightGradient,
})

const navClasses = classNames({
[styles.tabList]: true,
[styles.sticky]: sticky,
})

return (
<ul role="tablist" className={navClasses}>
{children}
</ul>
<section className={containerClasses} ref={containerRef}>
<ul role="tablist" className={navClasses} ref={navRef}>
{children}
</ul>
</section>
)
}

Expand Down
42 changes: 42 additions & 0 deletions src/components/SquareTabs/styles.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
.container {
position: relative;

&::before,
&::after {
position: absolute;
top: 0;
bottom: 0;
z-index: calc(var(--z-index-sticky-tabs) + 1);
width: 7.5rem;
pointer-events: none;
content: '';
opacity: 0; /* Initially hidden */
transition: opacity 0.3s;
}

&.showLeftGradient::before,
&.showRightGradient::after {
opacity: 1; /* Show when scrollable */
}

&::before {
left: 0;
background: linear-gradient(
-90deg,
rgb(255 255 255 / 0%) 0%,
rgb(255 255 255 / 30%) 20%,
#fff 100%
);
}

&::after {
right: 0;
background: linear-gradient(
90deg,
rgb(255 255 255 / 0%) 0%,
rgb(255 255 255 / 30%) 20%,
#fff 100%
);
}
}

.tabList {
@mixin hide-scrollbar;

Expand Down

0 comments on commit c2c1404

Please sign in to comment.