Skip to content

Commit

Permalink
feat: smoother type tab
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Apr 12, 2024
1 parent be6375f commit 07e7625
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 25 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
"@electron-toolkit/utils": "^3.0.0",
"@radix-ui/react-tabs": "1.0.4",
"@radix-ui/react-tooltip": "1.0.7",
"@use-gesture/react": "10.3.1",
"class-variance-authority": "0.7.0",
"clsx": "2.1.0",
"electron-updater": "^6.1.7",
"framer-motion": "11.0.27",
"lethargy": "1.0.9",
"react-router-dom": "6.22.3",
"tailwind-merge": "2.2.2",
"tailwindcss-animate": "1.0.7"
Expand Down
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 36 additions & 25 deletions src/renderer/src/components/type-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import {
TooltipProvider,
TooltipTrigger
} from '@renderer/components/ui/tooltip'
import { m, useScroll, useMotionValueEvent } from 'framer-motion'
import { useRef, useState } from 'react'
import { useWheel } from '@use-gesture/react'
import { Lethargy } from 'lethargy'
import { cn, clamp } from '@renderer/lib/utils'

function Content({ type }: { type: string }) {
return (
Expand All @@ -15,6 +17,8 @@ function Content({ type }: { type: string }) {
)
}

const lethargy = new Lethargy()

export function TypeTab() {
const items = [
{
Expand Down Expand Up @@ -50,47 +54,54 @@ export function TypeTab() {
]

const carouselRef = useRef<HTMLDivElement>(null)
const { scrollXProgress } = useScroll({
container: carouselRef
})

const [xProgress, setXProgress] = useState(0)
useMotionValueEvent(scrollXProgress, "change", (value) => {
setXProgress(value);
const [active, setActive] = useState(0)
useWheel(({ event, last, memo: wait = false, direction: [dx], delta: [dex] }) => {
if (!last) {
const s = lethargy.check(event)
if (s) {
if (!wait && Math.abs(dex) > 20) {
setActive((i) => clamp(i + dx, 0, items.length - 1))
return true
} else {
return undefined
}
} else {
return false
}
} else {
return false
}
}, {
target: carouselRef,
})

return (
<TooltipProvider delayDuration={300}>
<div className="flex text-zinc-500 w-full justify-around text-xl my-2">
{items.map((item, index) => (
<m.div
<div
key={item.name}
className={item.className}
style={{
filter: `grayscale(${Math.min(Math.abs(xProgress - 1 / (items.length - 1) * index) * (items.length - 1), 1) * 100}%)`,
}}
className={cn(item.className, active !== index && 'grayscale')}
onClick={() => {
if (carouselRef.current) {
carouselRef.current.scrollTo({
left: carouselRef.current.clientWidth * index,
behavior: 'smooth'
})
}
setActive(index)
}}
>
<Tooltip>
<TooltipTrigger>{item.icon}</TooltipTrigger>
<TooltipContent side="bottom">{item.name}</TooltipContent>
</Tooltip>
</m.div>
</div>
))}
</div>
<div className="w-full h-full flex snap-x snap-mandatory overflow-x-auto" ref={carouselRef}>
{items.map((item) => (
<section key={item.name} className="snap-center shrink-0">
<Content type={item.name} />
</section>
))}
<div className="w-full h-full overflow-x-hidden" ref={carouselRef}>
<div className="h-full flex transition-transform" style={{ transform: `translateX(${-active * 320}px)` }}>
{items.map((item) => (
<section key={item.name} className="snap-center shrink-0">
<Content type={item.name} />
</section>
))}
</div>
</div>
</TooltipProvider>
)
Expand Down
4 changes: 4 additions & 0 deletions src/renderer/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

export function clamp(value, min, max) {
return Math.max(Math.min(max, value), min)
}

0 comments on commit 07e7625

Please sign in to comment.