NavTabs.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <script setup lang="ts">
  2. import TabActiveSvg from '~/assets/icons/tab-active.svg'
  3. import MoreSvg from '~/assets/icons/more.svg'
  4. type NavTab = {
  5. label: string
  6. value: string
  7. }
  8. type FeaturedGame = {
  9. label: string
  10. image?: string
  11. isMore?: boolean
  12. }
  13. const assets = {
  14. gameMobile: 'https://www.figma.com/api/mcp/asset/caa36564-9d8d-4632-976c-9fc682b3d8d9',
  15. gameFreeFire: 'https://www.figma.com/api/mcp/asset/d475b197-3a66-4191-a968-215b443b6323',
  16. gamePubg: 'https://www.figma.com/api/mcp/asset/3931728a-428b-4f5e-a603-108352c802a3',
  17. } as const
  18. const navTabs: NavTab[] = [
  19. { label: 'Online Play', value: 'online' },
  20. { label: 'PC Game', value: 'pc' },
  21. { label: 'Activity', value: 'activity' },
  22. ]
  23. const featuredGames: FeaturedGame[] = [
  24. { label: 'Mobile Legends', image: assets.gameMobile },
  25. { label: 'FREE FIRE', image: assets.gameFreeFire },
  26. { label: 'PUBG', image: assets.gamePubg },
  27. { label: 'More', isMore: true },
  28. ]
  29. const activeTab = ref<NavTab['value']>(navTabs[0]?.value ?? '')
  30. const activeCategory = ref<FeaturedGame['label']>(featuredGames[0]?.label ?? '')
  31. </script>
  32. <template>
  33. <section>
  34. <nav class="flex items-center gap-4 text-base">
  35. <div
  36. v-for="tab in navTabs"
  37. :key="tab.value"
  38. class="relative flex items-center justify-center"
  39. :class="activeTab === tab.value ? 'text-text-primary text-title' : 'text-text-secondary'"
  40. @click="activeTab = tab.value"
  41. >
  42. <TabActiveSvg
  43. v-if="activeTab === tab.value"
  44. class="absolute z-0"
  45. />
  46. <span class="relative z-10 font-title">{{ tab.label }}</span>
  47. </div>
  48. </nav>
  49. <div class="mt-2 flex gap-4 overflow-x-auto no-scrollbar">
  50. <div
  51. v-for="game in featuredGames"
  52. :key="game.label"
  53. class="category-item flex min-w-[72px] flex-col items-center justify-end gap-1"
  54. @click="activeCategory = game.label"
  55. >
  56. <div
  57. v-if="activeCategory === game.label"
  58. class="category-item-active absolute z-0 mt-auto"
  59. />
  60. <div class="category-image flex relative z-10">
  61. <template v-if="game.image">
  62. <img
  63. :src="game.image"
  64. :alt="game.label"
  65. class="size-full"
  66. loading="lazy"
  67. >
  68. </template>
  69. <template v-else>
  70. <MoreSvg />
  71. </template>
  72. </div>
  73. <p class="max-w-full truncate font-sans text-xs font-light text-[#1b1919] relative shrink-0 z-10 mb-2">
  74. {{ game.label }}
  75. </p>
  76. </div>
  77. </div>
  78. </section>
  79. </template>
  80. <style lang="scss" scoped>
  81. .no-scrollbar {
  82. -ms-overflow-style: none;
  83. scrollbar-width: none;
  84. }
  85. .no-scrollbar::-webkit-scrollbar {
  86. display: none;
  87. }
  88. .category-item {
  89. width: 102px;
  90. .category-item-active {
  91. width: 102px;
  92. height: 68px;
  93. flex-shrink: 0;
  94. border-radius: 30px 12px 12px 12px;
  95. border: 1px solid #FFF;
  96. background: linear-gradient(228deg, #DEF8DE 0%, #BDF5FF 73.53%);
  97. }
  98. .category-image {
  99. @include size(50px, 50px);
  100. }
  101. }
  102. </style>