From 5456ae396fa9654506855e417dd0f9731a8fd740 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 18 Sep 2025 17:18:41 -0300 Subject: [PATCH 1/3] Added accordion --- frontend/components/ui/accordion.tsx | 58 ++++++ frontend/package-lock.json | 56 +++++ frontend/package.json | 2 + frontend/tailwind.config.ts | 293 +++++++++++++++------------ 4 files changed, 280 insertions(+), 129 deletions(-) create mode 100644 frontend/components/ui/accordion.tsx diff --git a/frontend/components/ui/accordion.tsx b/frontend/components/ui/accordion.tsx new file mode 100644 index 00000000..2be19b59 --- /dev/null +++ b/frontend/components/ui/accordion.tsx @@ -0,0 +1,58 @@ +"use client"; + +import * as AccordionPrimitive from "@radix-ui/react-accordion"; +import { ChevronDown } from "lucide-react"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Accordion = AccordionPrimitive.Root; + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AccordionItem.displayName = "AccordionItem"; + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className, + )} + {...props} + > + + {children} + + +)); +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)); + +AccordionContent.displayName = AccordionPrimitive.Content.displayName; + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 724ba48b..8eac145b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@microsoft/mgt-components": "^4.6.0", "@microsoft/mgt-msal2-provider": "^4.6.0", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-collapsible": "^1.1.11", @@ -19,6 +20,7 @@ "@radix-ui/react-navigation-menu": "^1.2.13", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.5", @@ -1215,6 +1217,37 @@ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "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 + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", @@ -1859,6 +1892,29 @@ } } }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "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 + } + } + }, "node_modules/@radix-ui/react-slider": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0fbc5f3d..85cfc48b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,6 +11,7 @@ "dependencies": { "@microsoft/mgt-components": "^4.6.0", "@microsoft/mgt-msal2-provider": "^4.6.0", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.2", "@radix-ui/react-collapsible": "^1.1.11", @@ -20,6 +21,7 @@ "@radix-ui/react-navigation-menu": "^1.2.13", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-select": "^2.2.5", + "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slider": "^1.3.6", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-switch": "^1.2.5", diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts index 30615ce3..00fe9044 100644 --- a/frontend/tailwind.config.ts +++ b/frontend/tailwind.config.ts @@ -14,135 +14,170 @@ const config = { "./src/**/*.{ts,tsx}", ], theme: { - container: { - center: true, - screens: { - "2xl": "1400px", - "3xl": "1500px", - }, - }, - extend: { - screens: { - xl: "1200px", - "2xl": "1400px", - "3xl": "1500px", - }, - keyframes: { - overlayShow: { - from: { opacity: 0 }, - to: { opacity: 1 }, - }, - contentShow: { - from: { - opacity: 0, - transform: "translate(-50%, -50%) scale(0.95)", - clipPath: "inset(50% 0)", - }, - to: { - opacity: 1, - transform: "translate(-50%, -50%) scale(1)", - clipPath: "inset(0% 0)", - }, - }, - wiggle: { - "0%, 100%": { transform: "scale(100%)" }, - "50%": { transform: "scale(120%)" }, - }, - }, - animation: { - overlayShow: "overlayShow 400ms cubic-bezier(0.16, 1, 0.3, 1)", - contentShow: "contentShow 400ms cubic-bezier(0.16, 1, 0.3, 1)", - wiggle: "wiggle 150ms ease-in-out 1", - }, - colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - hover: "hsl(var(--primary-hover))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - hover: "hsl(var(--secondary-hover))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - "accent-emerald-foreground": { - DEFAULT: "hsl(var(--accent-emerald-foreground))", - }, - "accent-pink-foreground": { - DEFAULT: "hsl(var(--accent-pink-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - "status-blue": "var(--status-blue)", - "status-green": "var(--status-green)", - "status-red": "var(--status-red)", - "status-yellow": "var(--status-yellow)", - "component-icon": "var(--component-icon)", - "flow-icon": "var(--flow-icon)", - "placeholder-foreground": "hsl(var(--placeholder-foreground))", - "datatype-blue": { - DEFAULT: "hsl(var(--datatype-blue))", - foreground: "hsl(var(--datatype-blue-foreground))", - }, - "datatype-yellow": { - DEFAULT: "hsl(var(--datatype-yellow))", - foreground: "hsl(var(--datatype-yellow-foreground))", - }, - "datatype-red": { - DEFAULT: "hsl(var(--datatype-red))", - foreground: "hsl(var(--datatype-red-foreground))", - }, - "datatype-emerald": { - DEFAULT: "hsl(var(--datatype-emerald))", - foreground: "hsl(var(--datatype-emerald-foreground))", - }, - "datatype-violet": { - DEFAULT: "hsl(var(--datatype-violet))", - foreground: "hsl(var(--datatype-violet-foreground))", - }, - warning: { - DEFAULT: "hsl(var(--warning))", - foreground: "hsl(var(--warning-foreground))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - fontFamily: { - sans: ["var(--font-sans)", ...fontFamily.sans], - mono: ["var(--font-mono)", ...fontFamily.mono], - chivo: ["var(--font-chivo)", ...fontFamily.sans], - }, - fontSize: { - xxs: "11px", - mmd: "13px", - }, - }, + container: { + center: true, + screens: { + '2xl': '1400px', + '3xl': '1500px' + } + }, + extend: { + screens: { + xl: '1200px', + '2xl': '1400px', + '3xl': '1500px' + }, + keyframes: { + overlayShow: { + from: { + opacity: 0 + }, + to: { + opacity: 1 + } + }, + contentShow: { + from: { + opacity: 0, + transform: 'translate(-50%, -50%) scale(0.95)', + clipPath: 'inset(50% 0)' + }, + to: { + opacity: 1, + transform: 'translate(-50%, -50%) scale(1)', + clipPath: 'inset(0% 0)' + } + }, + wiggle: { + '0%, 100%': { + transform: 'scale(100%)' + }, + '50%': { + transform: 'scale(120%)' + } + }, + 'accordion-down': { + from: { + height: '0' + }, + to: { + height: 'var(--radix-accordion-content-height)' + } + }, + 'accordion-up': { + from: { + height: 'var(--radix-accordion-content-height)' + }, + to: { + height: '0' + } + } + }, + animation: { + overlayShow: 'overlayShow 400ms cubic-bezier(0.16, 1, 0.3, 1)', + contentShow: 'contentShow 400ms cubic-bezier(0.16, 1, 0.3, 1)', + wiggle: 'wiggle 150ms ease-in-out 1', + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + }, + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))', + hover: 'hsl(var(--primary-hover))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))', + hover: 'hsl(var(--secondary-hover))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + 'accent-emerald-foreground': { + DEFAULT: 'hsl(var(--accent-emerald-foreground))' + }, + 'accent-pink-foreground': { + DEFAULT: 'hsl(var(--accent-pink-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + }, + 'status-blue': 'var(--status-blue)', + 'status-green': 'var(--status-green)', + 'status-red': 'var(--status-red)', + 'status-yellow': 'var(--status-yellow)', + 'component-icon': 'var(--component-icon)', + 'flow-icon': 'var(--flow-icon)', + 'placeholder-foreground': 'hsl(var(--placeholder-foreground))', + 'datatype-blue': { + DEFAULT: 'hsl(var(--datatype-blue))', + foreground: 'hsl(var(--datatype-blue-foreground))' + }, + 'datatype-yellow': { + DEFAULT: 'hsl(var(--datatype-yellow))', + foreground: 'hsl(var(--datatype-yellow-foreground))' + }, + 'datatype-red': { + DEFAULT: 'hsl(var(--datatype-red))', + foreground: 'hsl(var(--datatype-red-foreground))' + }, + 'datatype-emerald': { + DEFAULT: 'hsl(var(--datatype-emerald))', + foreground: 'hsl(var(--datatype-emerald-foreground))' + }, + 'datatype-violet': { + DEFAULT: 'hsl(var(--datatype-violet))', + foreground: 'hsl(var(--datatype-violet-foreground))' + }, + warning: { + DEFAULT: 'hsl(var(--warning))', + foreground: 'hsl(var(--warning-foreground))' + } + }, + borderRadius: { + lg: 'var(--radius)', + md: 'calc(var(--radius) - 2px)', + sm: 'calc(var(--radius) - 4px)' + }, + fontFamily: { + sans: [ + 'var(--font-sans)', + ...fontFamily.sans + ], + mono: [ + 'var(--font-mono)', + ...fontFamily.mono + ], + chivo: [ + 'var(--font-chivo)', + ...fontFamily.sans + ] + }, + fontSize: { + xxs: '11px', + mmd: '13px' + } + } }, plugins: [ tailwindcssAnimate, From 63cff406650909f576ba977714597260be998235 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 18 Sep 2025 17:18:51 -0300 Subject: [PATCH 2/3] changed ui elements, added separator --- frontend/components/ui/button.tsx | 42 +++++++++++++++++++++------- frontend/components/ui/card.tsx | 2 +- frontend/components/ui/separator.tsx | 31 ++++++++++++++++++++ 3 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 frontend/components/ui/separator.tsx diff --git a/frontend/components/ui/button.tsx b/frontend/components/ui/button.tsx index 87cb5c62..5d8b3287 100644 --- a/frontend/components/ui/button.tsx +++ b/frontend/components/ui/button.tsx @@ -8,13 +8,20 @@ const buttonVariants = cva( variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary-hover", - destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: "border border-input hover:bg-input hover:text-accent-foreground", - primary: "border bg-background text-secondary-foreground hover:bg-muted hover:shadow-sm", - warning: "bg-warning-foreground text-warning-text hover:bg-warning-foreground/90 hover:shadow-sm", - secondary: "border border-muted bg-muted text-secondary-foreground hover:bg-secondary-foreground/5", - ghost: "text-foreground hover:bg-accent hover:text-accent-foreground disabled:!bg-transparent", - ghostActive: "bg-muted text-foreground hover:bg-secondary-hover hover:text-accent-foreground", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input hover:bg-muted hover:text-accent-foreground", + primary: + "border bg-background text-secondary-foreground hover:bg-muted hover:shadow-sm", + warning: + "bg-warning-foreground text-warning-text hover:bg-warning-foreground/90 hover:shadow-sm", + secondary: + "border border-muted bg-muted text-secondary-foreground hover:bg-secondary-foreground/5", + ghost: + "text-foreground hover:bg-accent hover:text-accent-foreground disabled:!bg-transparent", + ghostActive: + "bg-muted text-foreground hover:bg-secondary-hover hover:text-accent-foreground", link: "underline-offset-4 hover:underline text-primary", }, size: { @@ -38,7 +45,9 @@ const buttonVariants = cva( function toTitleCase(text: string) { return text ?.split(" ") - ?.map((word) => word?.charAt(0)?.toUpperCase() + word?.slice(1)?.toLowerCase()) + ?.map( + (word) => word?.charAt(0)?.toUpperCase() + word?.slice(1)?.toLowerCase(), + ) ?.join(" "); } @@ -51,7 +60,20 @@ export interface ButtonProps } const Button = React.forwardRef( - ({ className, variant, size, loading, disabled, asChild = false, children, ignoreTitleCase = false, ...props }, ref) => { + ( + { + className, + variant, + size, + loading, + disabled, + asChild = false, + children, + ignoreTitleCase = false, + ...props + }, + ref, + ) => { const Comp = asChild ? Slot : "button"; let newChildren = children; if (typeof children === "string") { @@ -79,7 +101,7 @@ const Button = React.forwardRef( )} ); - } + }, ); Button.displayName = "Button"; diff --git a/frontend/components/ui/card.tsx b/frontend/components/ui/card.tsx index 210e2f19..b9bacd0d 100644 --- a/frontend/components/ui/card.tsx +++ b/frontend/components/ui/card.tsx @@ -64,7 +64,7 @@ const CardFooter = React.forwardRef< >(({ className, ...props }, ref) => (
)); diff --git a/frontend/components/ui/separator.tsx b/frontend/components/ui/separator.tsx new file mode 100644 index 00000000..3cc446d2 --- /dev/null +++ b/frontend/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client"; + +import * as SeparatorPrimitive from "@radix-ui/react-separator"; +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref, + ) => ( + + ), +); +Separator.displayName = SeparatorPrimitive.Root.displayName; + +export { Separator }; From 260099c52ecca7d66eb73e366842ef02c8f7dab6 Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Thu, 18 Sep 2025 17:18:59 -0300 Subject: [PATCH 3/3] added advanced part of onboarding --- frontend/components/label-wrapper.tsx | 57 +++++++++------- frontend/src/app/onboarding/advanced.tsx | 68 ++++++++++++++++++- .../src/app/onboarding/model-selector.tsx | 4 +- frontend/src/app/onboarding/page.tsx | 28 ++++++-- 4 files changed, 127 insertions(+), 30 deletions(-) diff --git a/frontend/components/label-wrapper.tsx b/frontend/components/label-wrapper.tsx index 75043a9e..ab785c5c 100644 --- a/frontend/components/label-wrapper.tsx +++ b/frontend/components/label-wrapper.tsx @@ -1,43 +1,54 @@ import { Info } from "lucide-react"; -import { - DropdownMenu, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { Input } from "./ui/input"; +import { cn } from "@/lib/utils"; import { Label } from "./ui/label"; import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; export function LabelWrapper({ label, + description, helperText, id, required, + flex, children, }: { label: string; - helperText: string; + description?: string; + helperText?: string; id: string; - required: boolean; + required?: boolean; + flex?: boolean; children: React.ReactNode; }) { return ( -
-