code-tabs.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. "use client";
  2. import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
  3. import { CopyButton } from "./copy-button";
  4. interface CodeTabsProps {
  5. tabs: {
  6. label: string;
  7. value: string;
  8. code: string;
  9. html: string;
  10. }[];
  11. defaultValue?: string;
  12. }
  13. export function CodeTabs({ tabs, defaultValue }: CodeTabsProps) {
  14. const defaultTab = defaultValue ?? tabs[0]?.value;
  15. return (
  16. <div className="my-6 rounded-lg border border-border bg-neutral-100 dark:bg-[#0a0a0a] text-sm font-mono overflow-hidden">
  17. <Tabs defaultValue={defaultTab} className="gap-0">
  18. <div className="flex items-center justify-between border-b border-border px-4 py-2">
  19. <TabsList className="h-7 bg-transparent p-0 gap-2">
  20. {tabs.map((tab) => (
  21. <TabsTrigger
  22. key={tab.value}
  23. value={tab.value}
  24. className="h-6 px-2 text-xs data-[state=active]:bg-secondary data-[state=active]:shadow-none rounded"
  25. >
  26. {tab.label}
  27. </TabsTrigger>
  28. ))}
  29. </TabsList>
  30. </div>
  31. {tabs.map((tab) => (
  32. <TabsContent
  33. key={tab.value}
  34. value={tab.value}
  35. className="relative group mt-0"
  36. >
  37. <div className="absolute top-3 right-3 z-10">
  38. <CopyButton
  39. text={tab.code}
  40. className="opacity-0 group-hover:opacity-100 text-neutral-500 dark:text-neutral-400 bg-neutral-100 dark:bg-[#0a0a0a]"
  41. />
  42. </div>
  43. <div
  44. className="overflow-x-auto [&_pre]:bg-transparent! [&_pre]:m-0! [&_pre]:p-4! [&_code]:bg-transparent! [&_.shiki]:bg-transparent!"
  45. dangerouslySetInnerHTML={{ __html: tab.html }}
  46. />
  47. </TabsContent>
  48. ))}
  49. </Tabs>
  50. </div>
  51. );
  52. }