1
0

preview-group.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. <script setup lang="ts">
  2. import type { SetupContext } from 'vue';
  3. import { computed, ref, useSlots } from 'vue';
  4. import { VbenTooltip } from '@vben-core/shadcn-ui';
  5. import { Code } from 'lucide-vue-next';
  6. import {
  7. TabsContent,
  8. TabsIndicator,
  9. TabsList,
  10. TabsRoot,
  11. TabsTrigger,
  12. } from 'radix-vue';
  13. defineOptions({
  14. inheritAttrs: false,
  15. });
  16. const props = withDefaults(
  17. defineProps<{
  18. files?: string[];
  19. }>(),
  20. { files: () => [] },
  21. );
  22. const open = ref(false);
  23. const slots: SetupContext['slots'] = useSlots();
  24. const tabs = computed(() => {
  25. return props.files.map((file) => {
  26. return {
  27. component: slots[file],
  28. label: file,
  29. };
  30. });
  31. });
  32. const currentTab = ref('index.vue');
  33. const toggleOpen = () => {
  34. open.value = !open.value;
  35. };
  36. </script>
  37. <template>
  38. <TabsRoot
  39. v-model="currentTab"
  40. class="bg-background-deep border-border overflow-hidden rounded-b-xl border-t"
  41. @update:model-value="open = true"
  42. >
  43. <div class="border-border bg-background flex border-b-2 pr-2">
  44. <div class="flex w-full items-center justify-between text-[13px]">
  45. <TabsList class="relative flex">
  46. <template v-if="open">
  47. <TabsIndicator
  48. class="absolute bottom-0 left-0 h-[2px] w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] rounded-full transition-[width,transform] duration-300"
  49. >
  50. <div class="size-full bg-[var(--vp-c-indigo-1)]"></div>
  51. </TabsIndicator>
  52. <TabsTrigger
  53. v-for="(tab, index) in tabs"
  54. :key="index"
  55. :value="tab.label"
  56. class="border-box text-foreground px-4 py-3 data-[state=active]:text-[var(--vp-c-indigo-1)]"
  57. tabindex="-1"
  58. >
  59. {{ tab.label }}
  60. </TabsTrigger>
  61. </template>
  62. </TabsList>
  63. <div
  64. :class="{
  65. 'py-2': !open,
  66. }"
  67. class="flex items-center"
  68. >
  69. <VbenTooltip side="top">
  70. <template #trigger>
  71. <Code
  72. class="hover:bg-accent size-7 cursor-pointer rounded-full p-1.5"
  73. @click="toggleOpen"
  74. />
  75. </template>
  76. {{ open ? 'Collapse code' : 'Expand code' }}
  77. </VbenTooltip>
  78. </div>
  79. </div>
  80. </div>
  81. <div
  82. :class="`${open ? 'h-[unset] max-h-[80vh]' : 'h-0'}`"
  83. class="block overflow-y-scroll bg-[var(--vp-code-block-bg)] transition-all duration-300"
  84. >
  85. <TabsContent
  86. v-for="tab in tabs"
  87. :key="tab.label"
  88. :value="tab.label"
  89. as-child
  90. class="rounded-xl"
  91. >
  92. <div class="text-foreground relative rounded-xl">
  93. <component :is="tab.component" class="border-0" />
  94. </div>
  95. </TabsContent>
  96. </div>
  97. </TabsRoot>
  98. </template>