Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions apps/web/components/apps/make/Setup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { InferGetServerSidePropsType } from "next";
import Link from "next/link";
import { useState } from "react";
import { Toaster } from "sonner";

Expand Down Expand Up @@ -134,9 +133,9 @@ export default function MakeSetup({ inviteLink }: InferGetServerSidePropsType<ty
<li>{t("make_setup_instructions_5")}</li>
<li>{t("make_setup_instructions_6")}</li>
</ol>
<Link href="/apps/installed/automation?hl=make" passHref={true} legacyBehavior>
<Button color="secondary">{t("done")}</Button>
</Link>
<Button href="/apps/installed/automation?hl=make" color="secondary">
{t("done")}
</Button>
</div>
</div>
</div>
Expand Down
7 changes: 3 additions & 4 deletions apps/web/components/apps/zapier/Setup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Link from "next/link";
import { useState } from "react";
import { Toaster } from "sonner";

Expand Down Expand Up @@ -138,9 +137,9 @@ export default function ZapierSetup(props: IZapierSetupProps) {
]}
/>
</ol>
<Link href="/apps/installed/automation?hl=zapier" passHref={true} legacyBehavior>
<Button color="secondary">{t("done")}</Button>
</Link>
<Button href="/apps/installed/automation?hl=zapier" color="secondary">
{t("done")}
</Button>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,10 @@ function Expired() {
<h2 className="text-emphasis text-center text-3xl font-extrabold">{t("request_is_expired")}</h2>
</div>
<p>{t("request_is_expired_instructions")}</p>
<Link href="/auth/forgot-password" passHref legacyBehavior>
<button
type="button"
className="flex w-full justify-center px-4 py-2 text-sm font-medium text-blue-600 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2">
{t("try_again")}
</button>
<Link
href="/auth/forgot-password"
className="flex w-full justify-center px-4 py-2 text-sm font-medium text-blue-600 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2">
{t("try_again")}
</Link>
</div>
</>
Expand Down
6 changes: 2 additions & 4 deletions apps/web/modules/bookings/views/bookings-single-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,7 @@ export default function Success(props: PageProps) {
<Link
href={`/auth/login?callbackUrl=${encodeURIComponent(
`/booking/${bookingInfo?.uid}`
)}`}
legacyBehavior>
)}`}>
{t("login")}
</Link>
</span>
Expand Down Expand Up @@ -849,8 +848,7 @@ export default function Success(props: PageProps) {
currentUserEmail
? `?rescheduledBy=${encodeURIComponent(currentUserEmail)}`
: ""
}`}
legacyBehavior>
}`}>
{t("reschedule")}
</Link>
</span>
Expand Down
12 changes: 4 additions & 8 deletions packages/app-store/_components/AppNotInstalledMessage.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -17,12 +15,10 @@ export default function AppNotInstalledMessage({ appName }: { appName: string })
<p className="text-subtle px-1 leading-normal">{t("visit_our_app_store")}</p>

<div className="mt-5">
<Link href={`/apps/${appName}`} passHref={true} legacyBehavior>
<Button type="button" color="secondary">
{t("go_to_app_store")}
<Icon name="arrow-up-right" className="ml-1" size={20} />
</Button>
</Link>
<Button href={`/apps/${appName}`} color="secondary">
{t("go_to_app_store")}
<Icon name="arrow-up-right" className="ml-1" size={20} />
</Button>
</div>
</div>
</div>
Expand Down
43 changes: 25 additions & 18 deletions packages/ui/components/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,21 +243,21 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, ButtonPr
// If pass an `href`-attr is passed it's `<a>`, otherwise it's a `<button />`
const isLink = typeof props.href !== "undefined";
const elementType = isLink ? "a" : "button";
const element = React.createElement(
elementType,
{
...passThroughProps,
disabled,
type: !isLink ? type : undefined,
ref: forwardedRef,
className: classNames(buttonClasses({ color, size, loading, variant }), props.className),
// if we click a disabled button, we prevent going through the click handler
onClick: disabled
? (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
e.preventDefault();
}
: props.onClick,
},

const elementProps = {
...passThroughProps,
disabled,
type: !isLink ? type : undefined,
className: classNames(buttonClasses({ color, size, loading, variant }), props.className),
// if we click a disabled button, we prevent going through the click handler
onClick: disabled
? (e: React.MouseEvent<HTMLElement, MouseEvent>) => {
e.preventDefault();
}
: props.onClick,
};

const elementContent = (
<>
{CustomStartIcon ||
(StartIcon && (
Expand Down Expand Up @@ -333,8 +333,15 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, ButtonPr
);

return props.href ? (
<Link data-testid="link-component" passHref href={props.href} shallow={shallow && shallow} legacyBehavior>
{element}
<Link
ref={forwardedRef as React.Ref<HTMLAnchorElement>}
{...(passThroughProps as React.AnchorHTMLAttributes<HTMLAnchorElement>)}
data-testid="link-component"
href={props.href}
shallow={shallow && shallow}
className={elementProps.className}
onClick={elementProps.onClick}>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forward the computed disabled flag to the Link so link-style buttons still receive the [disabled] attribute (required for the existing disabled:* styling when loading sets disabled implicitly).

Prompt for AI agents
Address the following comment on packages/ui/components/button/Button.tsx at line 343:

<comment>Forward the computed disabled flag to the Link so link-style buttons still receive the `[disabled]` attribute (required for the existing disabled:* styling when loading sets disabled implicitly).</comment>

<file context>
@@ -333,8 +333,15 @@ export const Button = forwardRef&lt;HTMLAnchorElement | HTMLButtonElement, ButtonPr
+      href={props.href}
+      shallow={shallow &amp;&amp; shallow}
+      className={elementProps.className}
+      onClick={elementProps.onClick}&gt;
+      {elementContent}
     &lt;/Link&gt;
</file context>
Fix with Cubic

{elementContent}
</Link>
) : (
<Wrapper
Expand All @@ -343,7 +350,7 @@ export const Button = forwardRef<HTMLAnchorElement | HTMLButtonElement, ButtonPr
tooltipSide={tooltipSide}
tooltipOffset={tooltipOffset}
tooltipClassName={tooltipClassName}>
{element}
{React.createElement(elementType, { ...elementProps, ref: forwardedRef }, elementContent)}
</Wrapper>
);
});
Expand Down
10 changes: 4 additions & 6 deletions packages/ui/components/dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,17 @@ type ButtonOrLinkProps = ComponentProps<"button"> & ComponentProps<"a">;

export function ButtonOrLink({ href, ...props }: ButtonOrLinkProps) {
const isLink = typeof href !== "undefined";
const ButtonOrLink = isLink ? "a" : "button";

const content = <ButtonOrLink {...props} />;

if (isLink) {
const { ref: _ref, ...linkProps } = props;
return (
<Link href={href} legacyBehavior>
{content}
<Link href={href} {...linkProps}>
{props.children}
</Link>
);
}

return content;
return <button {...props} />;
}

export const DropdownItem = (props: DropdownItemProps) => {
Expand Down
14 changes: 7 additions & 7 deletions packages/ui/components/form/step/Stepper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ function Stepper<T extends DefaultStep>(props: {
href={props.disableSteps ? "#" : `${href}?step=${index + 1}`}
shallow
replace
legacyBehavior>
{...(index + 1 === props.step ? { "aria-current": "step" } : {})}>
{index + 1 < props.step ? (
<a className="hover:bg-inverted block h-2.5 w-2.5 rounded-full bg-gray-600">
<span className="hover:bg-inverted block h-2.5 w-2.5 rounded-full bg-gray-600">
<span className="sr-only">{mapStep.title}</span>
</a>
</span>
) : index + 1 === props.step ? (
<a className="relative flex items-center justify-center" aria-current="step">
<span className="relative flex items-center justify-center">
<span className="absolute flex h-5 w-5 p-px" aria-hidden="true">
<span className="bg-emphasis h-full w-full rounded-full" />
</span>
Expand All @@ -45,11 +45,11 @@ function Stepper<T extends DefaultStep>(props: {
aria-hidden="true"
/>
<span className="sr-only">{mapStep.title}</span>
</a>
</span>
) : (
<a className="bg-emphasis block h-2.5 w-2.5 rounded-full hover:bg-gray-400">
<span className="bg-emphasis block h-2.5 w-2.5 rounded-full hover:bg-gray-400">
<span className="sr-only">{mapStep.title}</span>
</a>
</span>
)}
</Link>
</li>
Expand Down
42 changes: 20 additions & 22 deletions packages/ui/components/list/List.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Link from "next/link";
import { createElement } from "react";
import { AnchorHTMLAttributes, createElement } from "react";

import { useLocale } from "@calcom/lib/hooks/useLocale";
import classNames from "@calcom/ui/classNames";
Expand Down Expand Up @@ -37,31 +37,29 @@ export type ListItemProps = { expanded?: boolean; rounded?: boolean } & ({
export function ListItem(props: ListItemProps) {
const { href, expanded, rounded = true, ...passThroughProps } = props;

const elementType = href ? "a" : "li";

const element = createElement(
elementType,
{
...passThroughProps,
className: classNames(
"items-center bg-default min-w-0 flex-1 flex border-neutral-200 p-4 sm:mx-0 md:border md:p-4 xl:mt-0 border-subtle",
expanded ? "my-2 border" : "border -mb-px last:mb-0",
// Pass rounded false to not round the corners -> Useful when used in list we can use roundedContainer to create the right design
rounded ? "rounded-md" : "rounded-none",
props.className,
(props.onClick || href) && "hover:bg-muted"
),
"data-testid": "list-item",
},
props.children
);
const elementProps = {
...passThroughProps,
className: classNames(
"items-center bg-default min-w-0 flex-1 flex border-neutral-200 p-4 sm:mx-0 md:border md:p-4 xl:mt-0 border-subtle",
expanded ? "my-2 border" : "border -mb-px last:mb-0",
// Pass rounded false to not round the corners -> Useful when used in list we can use roundedContainer to create the right design
rounded ? "rounded-md" : "rounded-none",
props.className,
(props.onClick || href) && "hover:bg-muted"
),
"data-testid": "list-item",
};

return href ? (
<Link passHref href={href} legacyBehavior>
{element}
<Link
href={href}
className={elementProps.className}
data-testid={elementProps["data-testid"]}
{...(passThroughProps as AnchorHTMLAttributes<HTMLAnchorElement>)}>
{props.children}
</Link>
) : (
element
createElement("li", elementProps, props.children)
);
}

Expand Down
Loading