From 4bb2c471f111e0ee458a9858dd5ef645a926b2f1 Mon Sep 17 00:00:00 2001 From: "Pablo F.G" Date: Wed, 24 Jun 2026 11:42:11 +0200 Subject: [PATCH] refactor(ui): apply React 19 and styling guideline fixes - Replace forwardRef/useMemo/useCallback usages flagged in review - Drop default React import in invitation page - Use cn() instead of clsx in ThemeSwitch - Narrow eslint.config ignore list to explicit config files --- .../invitations/(send-invite)/new/page.tsx | 2 +- ui/components/ThemeSwitch.tsx | 6 +- .../invitations/workflow/vertical-steps.tsx | 379 +++++++++--------- .../roles/workflow/vertical-steps.tsx | 379 +++++++++--------- ui/components/ui/accordion/Accordion.tsx | 54 ++- ui/components/ui/action-card/ActionCard.tsx | 6 +- ui/eslint.config.ts | 6 +- 7 files changed, 413 insertions(+), 419 deletions(-) diff --git a/ui/app/(prowler)/invitations/(send-invite)/new/page.tsx b/ui/app/(prowler)/invitations/(send-invite)/new/page.tsx index 69485ba603..d0372c4f4b 100644 --- a/ui/app/(prowler)/invitations/(send-invite)/new/page.tsx +++ b/ui/app/(prowler)/invitations/(send-invite)/new/page.tsx @@ -1,4 +1,4 @@ -import React, { Suspense } from "react"; +import { Suspense } from "react"; import { getRoles } from "@/actions/roles"; import { SkeletonInvitationInfo } from "@/components/invitations/workflow"; diff --git a/ui/components/ThemeSwitch.tsx b/ui/components/ThemeSwitch.tsx index eae18202c9..430e33893a 100644 --- a/ui/components/ThemeSwitch.tsx +++ b/ui/components/ThemeSwitch.tsx @@ -4,7 +4,6 @@ import type { SwitchProps } from "@heroui/switch"; import { useSwitch } from "@heroui/switch"; import { useIsSSR } from "@react-aria/ssr"; import { VisuallyHidden } from "@react-aria/visually-hidden"; -import { clsx } from "clsx"; import { useTheme } from "next-themes"; import { FC } from "react"; @@ -13,6 +12,7 @@ import { TooltipContent, TooltipTrigger, } from "@/components/shadcn/tooltip"; +import { cn } from "@/lib/utils"; import { MoonFilledIcon, SunFilledIcon } from "./icons"; @@ -50,7 +50,7 @@ export const ThemeSwitch: FC = ({ = ({
{ * Callback function when the step index changes. */ onStepChange?: (stepIndex: number) => void; + /** + * The ref forwarded to the step buttons. + */ + ref?: Ref; } function CheckIcon(props: ComponentProps<"svg">) { @@ -87,205 +90,199 @@ function CheckIcon(props: ComponentProps<"svg">) { ); } -export const VerticalSteps = forwardRef( - ( - { - color = "primary", - steps = [], - defaultStep = 0, - onStepChange, - currentStep: currentStepProp, - hideProgressBars = false, - stepClassName, - className, - ...props - }, - ref, - ) => { - const [currentStep, setCurrentStep] = useControlledState( - currentStepProp, - defaultStep, - onStepChange, - ); +export const VerticalSteps = ({ + color = "primary", + steps = [], + defaultStep = 0, + onStepChange, + currentStep: currentStepProp, + hideProgressBars = false, + stepClassName, + className, + ref, + ...props +}: VerticalStepsProps) => { + const [currentStep, setCurrentStep] = useControlledState( + currentStepProp, + defaultStep, + onStepChange, + ); - const colors = useMemo(() => { - let userColor; - let fgColor; + const colors = (() => { + let userColor; + let fgColor; - const colorsVars = [ - "[--active-fg-color:var(--step-fg-color)]", - "[--active-border-color:var(--step-color)]", - "[--active-color:var(--step-color)]", - "[--complete-background-color:var(--step-color)]", - "[--complete-border-color:var(--step-color)]", - "[--inactive-border-color:hsl(var(--heroui-default-300))]", - "[--inactive-color:hsl(var(--heroui-default-300))]", - ]; + const colorsVars = [ + "[--active-fg-color:var(--step-fg-color)]", + "[--active-border-color:var(--step-color)]", + "[--active-color:var(--step-color)]", + "[--complete-background-color:var(--step-color)]", + "[--complete-border-color:var(--step-color)]", + "[--inactive-border-color:hsl(var(--heroui-default-300))]", + "[--inactive-color:hsl(var(--heroui-default-300))]", + ]; - switch (color) { - case "primary": - userColor = "[--step-color:var(--bg-button-primary)]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-primary-foreground))]"; - break; - case "secondary": - userColor = "[--step-color:hsl(var(--heroui-secondary))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-secondary-foreground))]"; - break; - case "success": - userColor = "[--step-color:hsl(var(--heroui-success))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-success-foreground))]"; - break; - case "warning": - userColor = "[--step-color:hsl(var(--heroui-warning))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-warning-foreground))]"; - break; - case "danger": - userColor = "[--step-color:hsl(var(--heroui-error))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-error-foreground))]"; - break; - case "default": - userColor = "[--step-color:hsl(var(--heroui-default))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-default-foreground))]"; - break; - default: - userColor = "[--step-color:hsl(var(--heroui-primary))]"; - fgColor = "[--step-fg-color:hsl(var(--heroui-primary-foreground))]"; - break; - } + switch (color) { + case "primary": + userColor = "[--step-color:var(--bg-button-primary)]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-primary-foreground))]"; + break; + case "secondary": + userColor = "[--step-color:hsl(var(--heroui-secondary))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-secondary-foreground))]"; + break; + case "success": + userColor = "[--step-color:hsl(var(--heroui-success))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-success-foreground))]"; + break; + case "warning": + userColor = "[--step-color:hsl(var(--heroui-warning))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-warning-foreground))]"; + break; + case "danger": + userColor = "[--step-color:hsl(var(--heroui-error))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-error-foreground))]"; + break; + case "default": + userColor = "[--step-color:hsl(var(--heroui-default))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-default-foreground))]"; + break; + default: + userColor = "[--step-color:hsl(var(--heroui-primary))]"; + fgColor = "[--step-fg-color:hsl(var(--heroui-primary-foreground))]"; + break; + } - if (!className?.includes("--step-fg-color")) colorsVars.unshift(fgColor); - if (!className?.includes("--step-color")) colorsVars.unshift(userColor); - if (!className?.includes("--inactive-bar-color")) - colorsVars.push( - "[--inactive-bar-color:hsl(var(--heroui-default-300))]", - ); + if (!className?.includes("--step-fg-color")) colorsVars.unshift(fgColor); + if (!className?.includes("--step-color")) colorsVars.unshift(userColor); + if (!className?.includes("--inactive-bar-color")) + colorsVars.push("[--inactive-bar-color:hsl(var(--heroui-default-300))]"); - return colorsVars; - }, [color, className]); + return colorsVars; + })(); - return ( -
+ {stepIdx < steps.length - 1 && !hideProgressBars && ( + + {stepIdx < steps.length - 1 && !hideProgressBars && ( +