index.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import type { FC } from 'react'
  2. import cn from '@/utils/classnames'
  3. type Option = {
  4. value: string
  5. text: string
  6. }
  7. type TabSliderProps = {
  8. className?: string
  9. itemWidth?: number
  10. value: string
  11. onChange: (v: string) => void
  12. options: Option[]
  13. }
  14. const TabSlider: FC<TabSliderProps> = ({
  15. className,
  16. itemWidth = 118,
  17. value,
  18. onChange,
  19. options,
  20. }) => {
  21. const currentIndex = options.findIndex(option => option.value === value)
  22. const current = options[currentIndex]
  23. return (
  24. <div className={cn(className, 'relative flex p-0.5 rounded-lg bg-gray-200')}>
  25. {
  26. options.map((option, index) => (
  27. <div
  28. key={option.value}
  29. className={`
  30. flex justify-center items-center h-7 text-[13px]
  31. font-semibold text-gray-600 rounded-[7px] cursor-pointer
  32. hover:bg-gray-50
  33. ${index !== options.length - 1 && 'mr-[1px]'}
  34. `}
  35. style={{
  36. width: itemWidth,
  37. }}
  38. onClick={() => onChange(option.value)}
  39. >
  40. {option.text}
  41. </div>
  42. ))
  43. }
  44. {
  45. current && (
  46. <div
  47. className={`
  48. absolute flex justify-center items-center h-7 bg-white text-[13px] font-semibold text-primary-600
  49. border-[0.5px] border-gray-200 rounded-[7px] shadow-xs transition-transform
  50. `}
  51. style={{
  52. width: itemWidth,
  53. transform: `translateX(${currentIndex * itemWidth + 1}px)`,
  54. }}
  55. >
  56. {current.text}
  57. </div>
  58. )
  59. }
  60. </div>
  61. )
  62. }
  63. export default TabSlider