"use client"; import NextLink from "next/link"; import { memo } from "react"; import type { MouseEventHandler, ReactNode } from "react"; import type { LinkTypeValue, LinkViewProps, LinkThemeValue, LinkVariantValue } from "./Link.types"; const FIGMA_ROOT = "21861:21428"; /** Profile & card small viewports: Figma Sizing/300 + label line (350). ≥640px: 18px / 1.3. */ const LINK_TYPOGRAPHY = "font-inter font-normal text-[length:var(--sizing-300)] leading-[var(--sizing-350)] min-[640px]:text-[18px] min-[640px]:leading-[1.3]"; function linkFocusRing(theme: LinkThemeValue) { return theme === "light" ? "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-[var(--color-border-link-focus)] focus-visible:rounded-lg" : "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-[var(--color-border-link-invert-focus)] focus-visible:rounded-lg"; } function defaultRootClass(theme: LinkThemeValue, linkType: LinkTypeValue) { const focusRing = linkFocusRing(theme); if (theme === "light" && linkType === "primary") { return `group inline-flex min-h-8 max-h-16 w-fit max-w-full shrink-0 items-center gap-2 rounded-lg ${LINK_TYPOGRAPHY} text-[var(--color-link-primary)] hover:text-[var(--color-link-primary-hover)] focus-visible:text-[var(--color-link-primary-focus)] active:text-[var(--color-link-primary-active)] ${focusRing}`; } if (theme === "light" && linkType === "secondary") { return `group inline-flex min-h-8 max-h-16 w-fit max-w-full shrink-0 items-center gap-2 rounded-lg ${LINK_TYPOGRAPHY} text-[var(--color-link-secondary)] hover:text-[var(--color-link-secondary-hover)] focus-visible:text-[var(--color-link-secondary-focus)] active:text-[var(--color-link-secondary-active)] ${focusRing}`; } if (theme === "dark" && linkType === "primary") { return `group inline-flex min-h-8 max-h-16 w-fit max-w-full shrink-0 items-center gap-2 rounded-lg ${LINK_TYPOGRAPHY} text-[var(--color-link-invert-primary)] hover:text-[var(--color-link-invert-primary-hover)] focus-visible:text-[var(--color-link-invert-primary-focus)] active:text-[var(--color-link-invert-primary-active)] ${focusRing}`; } return `group inline-flex min-h-8 max-h-16 w-fit max-w-full shrink-0 items-center gap-2 rounded-lg ${LINK_TYPOGRAPHY} text-[var(--color-link-invert-secondary)] hover:text-[var(--color-link-invert-secondary-hover)] focus-visible:text-[var(--color-link-invert-secondary-focus)] active:text-[var(--color-link-invert-secondary-active)] ${focusRing}`; } function defaultUnderlineClass(theme: LinkThemeValue, linkType: LinkTypeValue) { if (theme === "light" && linkType === "primary") { return "inline-block min-w-0 max-w-full border-b border-transparent bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-primary-hover)] group-focus-visible:border-[var(--color-link-primary-focus)] group-active:border-[var(--color-link-primary-active)]"; } if (theme === "light" && linkType === "secondary") { return "inline-block min-w-0 max-w-full border-b border-transparent bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-secondary-hover)] group-focus-visible:border-[var(--color-link-secondary-focus)] group-active:border-[var(--color-link-secondary-active)]"; } if (theme === "dark" && linkType === "primary") { return "inline-block min-w-0 max-w-full border-b border-transparent bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-invert-primary-hover)] group-focus-visible:border-[var(--color-link-invert-primary-focus)] group-active:border-[var(--color-link-invert-primary-active)]"; } return "inline-block min-w-0 max-w-full border-b border-transparent bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-invert-secondary-hover)] group-focus-visible:border-[var(--color-link-invert-secondary-focus)] group-active:border-[var(--color-link-invert-secondary-active)]"; } /** Same `pb-0.5` + `border-b` as default, but the rule is visible at rest. */ function paragraphUnderlineClass(theme: LinkThemeValue, linkType: LinkTypeValue) { if (theme === "light" && linkType === "primary") { return "inline-block min-w-0 max-w-full border-b border-[var(--color-link-primary)] bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-primary-hover)] group-focus-visible:border-[var(--color-link-primary-focus)] group-active:border-[var(--color-link-primary-active)]"; } if (theme === "light" && linkType === "secondary") { return "inline-block min-w-0 max-w-full border-b border-[var(--color-link-secondary)] bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-secondary-hover)] group-focus-visible:border-[var(--color-link-secondary-focus)] group-active:border-[var(--color-link-secondary-active)]"; } if (theme === "dark" && linkType === "primary") { return "inline-block min-w-0 max-w-full border-b border-[var(--color-link-invert-primary)] bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-invert-primary-hover)] group-focus-visible:border-[var(--color-link-invert-primary-focus)] group-active:border-[var(--color-link-invert-primary-active)]"; } return "inline-block min-w-0 max-w-full border-b border-[var(--color-link-invert-secondary)] bg-transparent px-0 pb-0.5 text-left text-inherit transition-[border-color] group-hover:border-[var(--color-link-invert-secondary-hover)] group-focus-visible:border-[var(--color-link-invert-secondary-focus)] group-active:border-[var(--color-link-invert-secondary-active)]"; } function LinkPlus12() { return ( ); } function LinkViewInner({ variant, theme, type, leadingIcon, trailingIcon, children, }: { variant: LinkVariantValue; theme: LinkThemeValue; type: LinkTypeValue; leadingIcon: boolean; trailingIcon: boolean; children: ReactNode; }) { if (variant === "paragraph") { return ( {children} ); } return ( <> {leadingIcon ? : null} {children} {trailingIcon ? : null} ); } function LinkView({ children, className, type, variant, theme, leadingIcon, trailingIcon, href, onClick, dataFigmaNode = FIGMA_ROOT, prefetch, replace, scroll, rel, target, id, "aria-label": ariaLabel, "aria-current": ariaCurrent, }: LinkViewProps) { const root = [defaultRootClass(theme, type), className] .filter(Boolean) .join(" "); const content = ( {children} ); if (href) { return ( | undefined} > {content} ); } return ( ); } LinkView.displayName = "LinkView"; export default memo(LinkView);