From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001 From: wwf <yearningwang@iqtogether.com> Date: 星期三, 04 六月 2025 15:17:49 +0800 Subject: [PATCH] 初始化 --- app/components/base/tab-slider/index.tsx | 107 +++++++++++++++++++++-------------------------------- 1 files changed, 43 insertions(+), 64 deletions(-) diff --git a/app/components/base/tab-slider/index.tsx b/app/components/base/tab-slider/index.tsx index fd6b876..03296a9 100644 --- a/app/components/base/tab-slider/index.tsx +++ b/app/components/base/tab-slider/index.tsx @@ -1,85 +1,64 @@ -import type { FC, ReactNode } from 'react' -import { useEffect, useState } from 'react' +import type { FC } from 'react' import cn from '@/utils/classnames' -import Badge, { BadgeState } from '@/app/components/base/badge/index' -import { useInstalledPluginList } from '@/service/use-plugins' + type Option = { value: string - text: ReactNode + text: string } - type TabSliderProps = { className?: string + itemWidth?: number value: string onChange: (v: string) => void options: Option[] } - const TabSlider: FC<TabSliderProps> = ({ className, + itemWidth = 118, value, onChange, options, }) => { - const [activeIndex, setActiveIndex] = useState(options.findIndex(option => option.value === value)) - const [sliderStyle, setSliderStyle] = useState({}) - const { data: pluginList } = useInstalledPluginList() - - const updateSliderStyle = (index: number) => { - const tabElement = document.getElementById(`tab-${index}`) - if (tabElement) { - const { offsetLeft, offsetWidth } = tabElement - setSliderStyle({ - transform: `translateX(${offsetLeft}px)`, - width: `${offsetWidth}px`, - }) - } - } - - useEffect(() => { - const newIndex = options.findIndex(option => option.value === value) - setActiveIndex(newIndex) - updateSliderStyle(newIndex) - }, [value, options, pluginList]) + const currentIndex = options.findIndex(option => option.value === value) + const current = options[currentIndex] return ( - <div className={cn(className, 'relative inline-flex items-center justify-center rounded-[10px] bg-components-segmented-control-bg-normal p-0.5')}> - <div - className="shadows-shadow-xs absolute bottom-0.5 left-0 right-0 top-0.5 rounded-[10px] bg-components-panel-bg transition-transform duration-300 ease-in-out" - style={sliderStyle} - /> - {options.map((option, index) => ( - <div - id={`tab-${index}`} - key={option.value} - className={cn( - 'relative z-10 flex cursor-pointer items-center justify-center gap-1 rounded-[10px] px-2.5 py-1.5 transition-colors duration-300 ease-in-out', - 'system-md-semibold', - index === activeIndex - ? 'text-text-primary' - : 'text-text-tertiary', - )} - onClick={() => { - if (index !== activeIndex) { - onChange(option.value) - updateSliderStyle(index) - } - }} - > - {option.text} - {/* if no plugin installed, the badge won't show */} - {option.value === 'plugins' - && (pluginList?.plugins.length ?? 0) > 0 - && <Badge - size='s' - uppercase={true} - state={BadgeState.Default} - > - {pluginList?.plugins.length} - </Badge> - } - </div> - ))} + <div className={cn(className, 'relative flex p-0.5 rounded-lg bg-gray-200')}> + { + options.map((option, index) => ( + <div + key={option.value} + className={` + flex justify-center items-center h-7 text-[13px] + font-semibold text-gray-600 rounded-[7px] cursor-pointer + hover:bg-gray-50 + ${index !== options.length - 1 && 'mr-[1px]'} + `} + style={{ + width: itemWidth, + }} + onClick={() => onChange(option.value)} + > + {option.text} + </div> + )) + } + { + current && ( + <div + className={` + absolute flex justify-center items-center h-7 bg-white text-[13px] font-semibold text-primary-600 + border-[0.5px] border-gray-200 rounded-[7px] shadow-xs transition-transform + `} + style={{ + width: itemWidth, + transform: `translateX(${currentIndex * itemWidth + 1}px)`, + }} + > + {current.text} + </div> + ) + } </div> ) } -- Gitblit v1.8.0