From 19ac0139c16a3f6ab8e4ea9855ddfda4238f602a Mon Sep 17 00:00:00 2001 From: Volnei Munhoz Date: Sun, 21 Dec 2025 09:40:27 -0300 Subject: [PATCH] fix: Remove all links legacyBehavior (#25585) * Remove all links legacyBehavior * fix: resolve type errors in Button and Dropdown when using Link without legacyBehavior - Button.tsx: Only pass ref to button element, not to Link (Link manages its own anchor) - Dropdown.tsx: Strip ref from props when using Link to avoid type incompatibility This fixes the type errors that were causing API V1 and V2 builds to fail. Co-Authored-By: Volnei Munhoz * fix: only pass disabled and type props to button element, not to Link Link component doesn't accept disabled or type props, so these should only be passed when rendering a button element. Co-Authored-By: Volnei Munhoz * fix: strip ref from passThroughProps when rendering Link The passThroughProps spread was including a ref property that's incompatible with Link's expected ref type. This strips the ref when rendering a Link component. Co-Authored-By: Volnei Munhoz * fix: use type assertion for React.createElement props to handle union types The Button component uses a union type for props that can be either Link or button props. TypeScript can't narrow the union type properly when using React.createElement with a dynamic element type, so we use a type assertion to cast the props to the correct type. Co-Authored-By: Volnei Munhoz * fix: render Link and button separately to avoid type conflicts Co-Authored-By: Volnei Munhoz * fix: preserve data-testid when rendering Button as Link Co-Authored-By: Volnei Munhoz --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- apps/web/components/apps/make/Setup.tsx | 10 ++-- .../[id]/forgot-password-single-view.tsx | 10 ++-- .../bookings/views/bookings-single-view.tsx | 39 ++++++------ .../_components/AppNotInstalledMessage.tsx | 12 ++-- packages/ui/components/button/Button.tsx | 58 ++++++++++-------- packages/ui/components/dropdown/Dropdown.tsx | 13 ++-- packages/ui/components/form/step/Stepper.tsx | 59 +++++++++++-------- packages/ui/components/list/List.tsx | 2 +- 8 files changed, 103 insertions(+), 100 deletions(-) diff --git a/apps/web/components/apps/make/Setup.tsx b/apps/web/components/apps/make/Setup.tsx index 105339b2d1..f51599ce3d 100644 --- a/apps/web/components/apps/make/Setup.tsx +++ b/apps/web/components/apps/make/Setup.tsx @@ -1,5 +1,4 @@ import type { InferGetServerSidePropsType } from "next"; -import Link from "next/link"; import { useState } from "react"; import { Toaster } from "sonner"; @@ -71,9 +70,10 @@ export default function MakeSetup({ inviteLink }: InferGetServerSidePropsType
+ {/* eslint-disable @next/next/no-img-element */} Make Logo
-
+
{t("setting_up_make")}
<> @@ -134,9 +134,9 @@ export default function MakeSetup({ inviteLink }: InferGetServerSidePropsType{t("make_setup_instructions_5")}
  • {t("make_setup_instructions_6")}
  • - - - +
    diff --git a/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx b/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx index acd1397da7..66056bf1f4 100644 --- a/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx +++ b/apps/web/modules/auth/forgot-password/[id]/forgot-password-single-view.tsx @@ -45,12 +45,10 @@ function Expired() {

    {t("request_is_expired")}

    {t("request_is_expired_instructions")}

    - - + + {t("try_again")} diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx index 4f45739c53..e7acd2d831 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.tsx @@ -53,7 +53,6 @@ import { EmptyScreen } from "@calcom/ui/components/empty-screen"; import { EmailInput, TextArea } from "@calcom/ui/components/form"; import { Icon } from "@calcom/ui/components/icon"; import { showToast } from "@calcom/ui/components/toast"; -import { Tooltip } from "@calcom/ui/components/tooltip"; import { useCalcomTheme } from "@calcom/ui/styles"; import CancelBooking from "@calcom/web/components/booking/CancelBooking"; import EventReservationSchema from "@calcom/web/components/schemas/EventReservationSchema"; @@ -801,15 +800,14 @@ export default function Success(props: PageProps) { {/* Login button but redirect to here */} - - - {t("login")} - - + + {t("login")} + @@ -839,17 +837,16 @@ export default function Success(props: PageProps) { canReschedule && !isRescheduleDisabled && ( - - - {t("reschedule")} - - + + {t("reschedule")} + {!isBookingInPast && canCancel && ( {t("or_lowercase")} )} diff --git a/packages/app-store/_components/AppNotInstalledMessage.tsx b/packages/app-store/_components/AppNotInstalledMessage.tsx index 5a9ce94d3b..b2d293c7f2 100644 --- a/packages/app-store/_components/AppNotInstalledMessage.tsx +++ b/packages/app-store/_components/AppNotInstalledMessage.tsx @@ -1,5 +1,3 @@ -import Link from "next/link"; - import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button } from "@calcom/ui/components/button"; import { Icon } from "@calcom/ui/components/icon"; @@ -17,12 +15,10 @@ export default function AppNotInstalledMessage({ appName }: { appName: string })

    {t("visit_our_app_store")}

    - - - +
    diff --git a/packages/ui/components/button/Button.tsx b/packages/ui/components/button/Button.tsx index fcd87c1f9d..f5810ce570 100644 --- a/packages/ui/components/button/Button.tsx +++ b/packages/ui/components/button/Button.tsx @@ -239,25 +239,17 @@ export const Button = forwardRef`, otherwise it's a ` ); }); diff --git a/packages/ui/components/dropdown/Dropdown.tsx b/packages/ui/components/dropdown/Dropdown.tsx index 3a8e168f53..599505e2ea 100644 --- a/packages/ui/components/dropdown/Dropdown.tsx +++ b/packages/ui/components/dropdown/Dropdown.tsx @@ -143,19 +143,14 @@ type ButtonOrLinkProps = ComponentProps<"button"> & ComponentProps<"a">; export function ButtonOrLink({ href, ...props }: ButtonOrLinkProps) { const isLink = typeof href !== "undefined"; - const ButtonOrLink = isLink ? "a" : "button"; - - const content = ; if (isLink) { - return ( - - {content} - - ); + // Strip ref from props when using Link (Link manages its own anchor element) + const { ref: _ref, ...linkProps } = props; + return ; } - return content; + return