From 0b3eda1fefb38ca2b1685578f7c27af66ea27124 Mon Sep 17 00:00:00 2001 From: Bianca Date: Tue, 14 Apr 2026 18:03:26 +0200 Subject: [PATCH 1/5] feat: add Tabs component using Radix UI --- package.json | 3 +- pnpm-lock.yaml | 62 +++++++++++++++++++++++++++++++++ src/components/ui/tabs.tsx | 71 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/components/ui/tabs.tsx diff --git a/package.json b/package.json index 0ccd5e6..4f52409 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tabs": "^1.1.13", "@t3-oss/env-nextjs": "^0.13.10", "@tanstack/react-table": "^8.21.3", "babel-plugin-react-compiler": "^1.0.0", @@ -49,4 +50,4 @@ "engines": { "node": ">=24.5.2" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c9e7c1..3ba7519 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: '@radix-ui/react-slot': specifier: ^1.2.4 version: 1.2.4(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-tabs': + specifier: ^1.1.13 + version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@t3-oss/env-nextjs': specifier: ^0.13.10 version: 0.13.10(typescript@5.9.3)(zod@4.2.1) @@ -592,6 +595,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-select@2.2.6': resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} peerDependencies: @@ -636,6 +652,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-tabs@1.1.13': + resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-use-callback-ref@1.1.1': resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: @@ -1552,6 +1581,23 @@ snapshots: '@types/react': 19.2.7 '@types/react-dom': 19.2.3(@types/react@19.2.7) + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/number': 1.1.1 @@ -1604,6 +1650,22 @@ snapshots: optionalDependencies: '@types/react': 19.2.7 + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.7)(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.7)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.7)(react@19.2.3)': dependencies: react: 19.2.3 diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx new file mode 100644 index 0000000..d2813bb --- /dev/null +++ b/src/components/ui/tabs.tsx @@ -0,0 +1,71 @@ +"use client" + +import * as TabsPrimitive from "@radix-ui/react-tabs" +import { cva, type VariantProps } from "class-variance-authority" +import type * as React from "react" + +import { cn } from "@/lib/utils" + +function Tabs({ className, orientation = "horizontal", ...props }: React.ComponentProps) { + return ( + + ) +} + +const tabsListVariants = cva( + "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-slate-500 group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none dark:text-slate-400", + { + variants: { + variant: { + default: "bg-slate-100 dark:bg-slate-800", + line: "gap-1 bg-transparent", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function TabsList({ + className, + variant = "default", + ...props +}: React.ComponentProps & VariantProps) { + return ( + + ) +} + +function TabsTrigger({ className, ...props }: React.ComponentProps) { + return ( + + ) +} + +function TabsContent({ className, ...props }: React.ComponentProps) { + return +} + +export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants } From 4af74fc847d2feb59a1a6efaabaf358ac5f31bd3 Mon Sep 17 00:00:00 2001 From: Bianca Date: Wed, 15 Apr 2026 10:57:48 +0200 Subject: [PATCH 2/5] feat: implement Tabs component with additional triggers for FAQs --- src/app/faqs/page.tsx | 40 ++++++++++++++++++++++ src/components/ui/tabs.tsx | 69 ++++++++++++++------------------------ 2 files changed, 65 insertions(+), 44 deletions(-) create mode 100644 src/app/faqs/page.tsx diff --git a/src/app/faqs/page.tsx b/src/app/faqs/page.tsx new file mode 100644 index 0000000..f510883 --- /dev/null +++ b/src/app/faqs/page.tsx @@ -0,0 +1,40 @@ +import { FiBookOpen, FiDollarSign, FiEdit, FiFileText, FiSend } from "react-icons/fi" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" + +export default function Home() { + return ( +
+
+ + + + + Lezioni + + + + Tasse + + + + Esami + + + + Piano di Studi + + + + Mobilitá Internazionale + + + Content for Tab 1 + Content for Tab 2 + Content for Tab 3 + Content for Tab 4 + Content for Tab 5 + +
+
+ ) +} diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx index d2813bb..75fd48b 100644 --- a/src/components/ui/tabs.tsx +++ b/src/components/ui/tabs.tsx @@ -1,66 +1,47 @@ "use client" import * as TabsPrimitive from "@radix-ui/react-tabs" -import { cva, type VariantProps } from "class-variance-authority" import type * as React from "react" import { cn } from "@/lib/utils" +import { Glass } from "../glass" -function Tabs({ className, orientation = "horizontal", ...props }: React.ComponentProps) { - return ( - - ) +function Tabs({ className, ...props }: React.ComponentProps) { + return } -const tabsListVariants = cva( - "group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-slate-500 group-data-[orientation=horizontal]/tabs:h-9 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none dark:text-slate-400", - { - variants: { - variant: { - default: "bg-slate-100 dark:bg-slate-800", - line: "gap-1 bg-transparent", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) - -function TabsList({ - className, - variant = "default", - ...props -}: React.ComponentProps & VariantProps) { +function TabsList({ className, children, ...props }: React.ComponentProps) { return ( - + + + {children} + + ) } -function TabsTrigger({ className, ...props }: React.ComponentProps) { +function TabsTrigger({ className, children, ...props }: React.ComponentProps) { return ( + > + ) } @@ -68,4 +49,4 @@ function TabsContent({ className, ...props }: React.ComponentProps } -export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants } +export { Tabs, TabsList, TabsTrigger, TabsContent } From 91ae04b17ea3ae66a8714a9b050cc081c2f457a5 Mon Sep 17 00:00:00 2001 From: Bianca Date: Thu, 16 Apr 2026 10:12:09 +0200 Subject: [PATCH 3/5] fix: rename to FAQsPage for clarity --- src/app/faqs/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/faqs/page.tsx b/src/app/faqs/page.tsx index f510883..78815dc 100644 --- a/src/app/faqs/page.tsx +++ b/src/app/faqs/page.tsx @@ -1,7 +1,7 @@ import { FiBookOpen, FiDollarSign, FiEdit, FiFileText, FiSend } from "react-icons/fi" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" -export default function Home() { +export default function FAQsPage() { return (
From 31f7db61ec845be33eab0a071076fe877c3d6322 Mon Sep 17 00:00:00 2001 From: Bianca Date: Thu, 16 Apr 2026 10:58:25 +0200 Subject: [PATCH 4/5] refactor: simplify FAQ tab rendering --- src/app/faqs/page.tsx | 69 +++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/app/faqs/page.tsx b/src/app/faqs/page.tsx index 78815dc..588f930 100644 --- a/src/app/faqs/page.tsx +++ b/src/app/faqs/page.tsx @@ -1,38 +1,57 @@ import { FiBookOpen, FiDollarSign, FiEdit, FiFileText, FiSend } from "react-icons/fi" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +const faqItems = [ + { + value: "tab1", + label: "Lezioni", + content: "Content for Tab 1", + icon: FiBookOpen, + }, + { + value: "tab2", + label: "Tasse", + content: "Content for Tab 2", + icon: FiDollarSign, + }, + { + value: "tab3", + label: "Esami", + content: "Content for Tab 3", + icon: FiEdit, + }, + { + value: "tab4", + label: "Piano di Studi", + content: "Content for Tab 4", + icon: FiFileText, + }, + { + value: "tab5", + label: "Mobilitá Internazionale", + content: "Content for Tab 5", + icon: FiSend, + }, +] + export default function FAQsPage() { return (
- - - Lezioni - - - - Tasse - - - - Esami - - - - Piano di Studi - - - - Mobilitá Internazionale - + {faqItems.map((item) => ( + + + {item.label} + + ))} - Content for Tab 1 - Content for Tab 2 - Content for Tab 3 - Content for Tab 4 - Content for Tab 5 + {faqItems.map((item) => ( + + {item.content} + + ))}
From 523e6ebc2b8b7eb94edccdca4df2e5bb544fda0d Mon Sep 17 00:00:00 2001 From: Bianca Date: Thu, 16 Apr 2026 11:37:22 +0200 Subject: [PATCH 5/5] feat: add TabsNavigation component for improved tab rendering --- src/app/faqs/page.tsx | 40 ++++++++++++------------ src/components/tabs-navigation/index.tsx | 20 ++++++++++++ src/components/tabs-navigation/types.ts | 12 +++++++ 3 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 src/components/tabs-navigation/index.tsx create mode 100644 src/components/tabs-navigation/types.ts diff --git a/src/app/faqs/page.tsx b/src/app/faqs/page.tsx index 588f930..8554e3e 100644 --- a/src/app/faqs/page.tsx +++ b/src/app/faqs/page.tsx @@ -1,5 +1,6 @@ import { FiBookOpen, FiDollarSign, FiEdit, FiFileText, FiSend } from "react-icons/fi" -import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import TabsNavigation from "@/components/tabs-navigation" +import { Tabs, TabsContent } from "@/components/ui/tabs" const faqItems = [ { @@ -29,31 +30,30 @@ const faqItems = [ { value: "tab5", label: "Mobilitá Internazionale", - content: "Content for Tab 5", + content: ( +
+

Content for Tab 5

+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. +

+
+ ), icon: FiSend, }, ] export default function FAQsPage() { return ( -
-
- - - {faqItems.map((item) => ( - - - {item.label} - - ))} - - {faqItems.map((item) => ( - - {item.content} - - ))} - -
+
+ + + {faqItems.map((item) => ( + + {item.content} + + ))} +
) } diff --git a/src/components/tabs-navigation/index.tsx b/src/components/tabs-navigation/index.tsx new file mode 100644 index 0000000..2c0db1f --- /dev/null +++ b/src/components/tabs-navigation/index.tsx @@ -0,0 +1,20 @@ +import { TabsList, TabsTrigger } from "@/components/ui/tabs" +import { cn } from "@/lib/utils" +import type { TabsNavigationProps } from "./types" + +export default function TabsNavigation({ items, className }: TabsNavigationProps) { + return ( + + {items.map((item) => { + const Icon = item.icon + + return ( + + {Icon && } + {item.label} + + ) + })} + + ) +} diff --git a/src/components/tabs-navigation/types.ts b/src/components/tabs-navigation/types.ts new file mode 100644 index 0000000..3606ff3 --- /dev/null +++ b/src/components/tabs-navigation/types.ts @@ -0,0 +1,12 @@ +import type { IconType } from "react-icons" + +export type TabsNavigationItem = { + value: string + label: string + icon?: IconType +} + +export type TabsNavigationProps = { + items: TabsNavigationItem[] + className?: string +}