From 07e76259cb2d32f666b8f34624ab1337bd95a87b Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 12 Apr 2024 10:20:09 +0800 Subject: [PATCH] feat: smoother type tab --- package.json | 2 + pnpm-lock.yaml | 23 +++++++++ src/renderer/src/components/type-tab.tsx | 61 ++++++++++++++---------- src/renderer/src/lib/utils.ts | 4 ++ 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index b0aab0da7..8ac9999d3 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7fe2c72f5..25dbd6fbc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ dependencies: '@radix-ui/react-tooltip': specifier: 1.0.7 version: 1.0.7(@types/react-dom@18.2.24)(@types/react@18.2.75)(react-dom@18.2.0)(react@18.2.0) + '@use-gesture/react': + specifier: 10.3.1 + version: 10.3.1(react@18.2.0) class-variance-authority: specifier: 0.7.0 version: 0.7.0 @@ -29,6 +32,9 @@ dependencies: framer-motion: specifier: 11.0.27 version: 11.0.27(react-dom@18.2.0)(react@18.2.0) + lethargy: + specifier: 1.0.9 + version: 1.0.9 react-router-dom: specifier: 6.22.3 version: 6.22.3(react-dom@18.2.0)(react@18.2.0) @@ -1954,6 +1960,19 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@use-gesture/core@10.3.1: + resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==} + dev: false + + /@use-gesture/react@10.3.1(react@18.2.0): + resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==} + peerDependencies: + react: '>= 16.8.0' + dependencies: + '@use-gesture/core': 10.3.1 + react: 18.2.0 + dev: false + /@vitejs/plugin-react@4.2.1(vite@5.2.8): resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} @@ -4088,6 +4107,10 @@ packages: readable-stream: 2.3.8 dev: true + /lethargy@1.0.9: + resolution: {integrity: sha512-nFM8blpCF9rqIL5mRAaTGc78W8oQixVtsD86jbEPvcI13+lDUYJf3R7DZQQL7tCiBpbGpGKMX2gwJFO9hiaOkg==} + dev: false + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} diff --git a/src/renderer/src/components/type-tab.tsx b/src/renderer/src/components/type-tab.tsx index de90418b6..6b6545f81 100644 --- a/src/renderer/src/components/type-tab.tsx +++ b/src/renderer/src/components/type-tab.tsx @@ -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 ( @@ -15,6 +17,8 @@ function Content({ type }: { type: string }) { ) } +const lethargy = new Lethargy() + export function TypeTab() { const items = [ { @@ -50,47 +54,54 @@ export function TypeTab() { ] const carouselRef = useRef(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 (
{items.map((item, index) => ( - { - if (carouselRef.current) { - carouselRef.current.scrollTo({ - left: carouselRef.current.clientWidth * index, - behavior: 'smooth' - }) - } + setActive(index) }} > {item.icon} {item.name} - +
))} -
- {items.map((item) => ( -
- -
- ))} +
+
+ {items.map((item) => ( +
+ +
+ ))} +
) diff --git a/src/renderer/src/lib/utils.ts b/src/renderer/src/lib/utils.ts index d084ccade..1a23efe60 100644 --- a/src/renderer/src/lib/utils.ts +++ b/src/renderer/src/lib/utils.ts @@ -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) +}