# Link Component

A simple, semantic link component for wrapping content (text, icons, images) with clickable links. Designed for minimal visual styling while maintaining accessibility and flexibility.

## Import path
```tsx
import Link from '@hubspot/cms-component-library/Link';
```

## Purpose

The Link component provides a lightweight wrapper for making content clickable without the visual weight of a button. It's distinct from the Button component in both purpose and appearance:

- **Link**: Simple content wrapper with minimal styling (this component)
- **Button**: Visual UI button with prominent styling (use even when the button functions as a link)

## When to Use Link vs Button

**Use Link when:**
- Wrapping icons or images with links
- Creating navigation menu items
- Inline text links within content
- Clickable content that doesn't need button-like appearance

**Use Button when:**
- Creating call-to-action elements
- Prominent navigation that should look like a button
- Form submissions or actions
- Any element that needs button-like visual emphasis

## Component Structure

```
Link/
├── index.tsx                     # Main component
├── types.ts                      # TypeScript type definitions
├── ContentFields.tsx             # HubSpot field definitions
├── StyleFields.tsx               # HubSpot style field definitions
├── index.module.scss             # SCSS module with design tokens
└── stories/
    ├── Link.stories.tsx          # Storybook examples
    ├── LinkDecorator.tsx         # Storybook decorator
    └── LinkDecorator.module.css  # Decorator styles
```

## Props

The Link component supports **two mutually exclusive usage patterns**. You must use one approach or the other, but **NOT BOTH**.

### Pattern 1: Field-based (Recommended for HubSpot CMS)

Pass a `linkField` prop containing HubSpot link field data. The component automatically extracts href, target, and rel values.

```tsx
{
  linkField: {                                       // HubSpot link field value
    url?: { href?: string; type?: string };          // Link URL object
    open_in_new_tab?: boolean;                       // Open in new tab
    no_follow?: boolean;                             // Add nofollow rel
  };
  variant?: 'primaryLink' | 'secondaryLink';         // Visual style variant (default: 'primaryLink')
  className?: string;                                // Additional CSS classes
  style?: React.CSSProperties;                       // Inline styles
  children?: React.ReactNode;                        // Link text/content
}
```

### Pattern 2: Manual (For Custom/Programmatic Usage)

Pass individual `href`, `target`, and `rel` props directly.

```tsx
{
  href: string;                                      // Link destination URL (required)
  target?: '_self' | '_blank' | '_parent' | '_top';  // Link target behavior
  rel?: string;                                      // Link relationship (e.g., 'noopener noreferrer')
  variant?: 'primaryLink' | 'secondaryLink';         // Visual style variant (default: 'primaryLink')
  className?: string;                                // Additional CSS classes
  style?: React.CSSProperties;                       // Inline styles
  children?: React.ReactNode;                        // Link text/content
}
```

**TypeScript enforces this pattern** - you cannot use `linkField` together with `href`/`target`/`rel`.

## Usage Examples

### Pattern 1: Field-based (Recommended for HubSpot CMS)

#### Basic Field-based Link

```tsx
import Link from '@hubspot/cms-component-library/Link';

// In a HubSpot module:
export default function MyModule({ fieldValues }) {
  return (
    <Link linkField={fieldValues.link}>
      {fieldValues.linkText}
    </Link>
  );
}
```

#### Field-based Link with Variant

```tsx
<Link
  linkField={fieldValues.link}
  variant="secondaryLink"
>
  Visit HubSpot
</Link>
```

### Pattern 2: Manual (For Custom/Programmatic Usage)

#### Basic Manual Link

```tsx
import Link from '@hubspot/cms-component-library/Link';

<Link href="https://www.hubspot.com">
  Visit HubSpot
</Link>
```

#### External Link (New Tab)

```tsx
<Link
  href="https://www.hubspot.com"
  target="_blank"
>
  Open in New Tab
</Link>
```

#### Navigation Menu

```tsx
<nav>
  <Link href="/home">Home</Link>
  <Link href="/about">About</Link>
  <Link href="/contact">Contact</Link>
</nav>
```

### Using Variants

```tsx
<Link href="https://www.hubspot.com" variant="primaryLink">
  Primary Link
</Link>

<Link href="https://www.hubspot.com" variant="secondaryLink">
  Secondary Link
</Link>
```

## HubSpot CMS Integration

### Field Definitions

The Link component provides field definitions for easy integration with HubSpot CMS modules.

#### ContentFields

```tsx
<Link.ContentFields
  linkLabel="Link URL"
  linkName="link"
  linkDefault={{
    url: {
      type: 'EXTERNAL',
      content_id: null,
      href: 'https://www.hubspot.com',
    },
  }}
/>
```

**Props:**
- `linkLabel?: string` — label for the LinkField (default: `'Link'`)
- `linkName?: string` — field name (default: `'link'`)
- `linkDefault?` — default value for the LinkField
- `fieldVisibility?: Partial<Record<string, Visibility>>` — visibility options keyed by field name (keys must match the corresponding field name prop, e.g. `linkName`). Values match the cms-components Visibility schema (e.g. `hidden_subfields`, `controlling_field_path`, `operator`)

**Example — hide the nofollow option:**
```tsx
<Link.ContentFields
  fieldVisibility={{ link: { hidden_subfields: { no_follow: true } } }}
/>
```

**Fields:**
- `link`: LinkField for href destination

#### StyleFields

```tsx
<Link.StyleFields
  variantLabel="Link style"
  variantName="linkVariant"
  variantDefault={{ variant_name: 'primaryLink' }}
/>
```

**Fields:**
- `linkVariant`: VariantSelectionField for theme variant selection (primaryLink, secondaryLink)

### Module Usage Example

**Recommended (Field-based):**

```tsx
import Link from '@hubspot/cms-component-library/Link';

export default function NavigationModule({ fieldValues }) {
  return (
    <Link
      linkField={fieldValues.link}
      variant={fieldValues.style.linkVariant?.variantName}
    >
      {fieldValues.linkText}
    </Link>
  );
}
```

**Manual (only when needed):**

```tsx
export default function NavigationModule({ fieldValues }) {
  return (
    <Link
      href="https://www.hubspot.com"
      target="_blank"
      rel="nofollow"
      variant="primaryLink"
    >
      Go to HubSpot
    </Link>
  );
}
```

Note: The field-based approach is simpler and less error-prone.

## Styling

### Variants

The Link component supports two visual style variants through the `variant` prop:

- **primaryLink** (default): Default link styling
- **secondaryLink**: Alternative link styling

The component renders a `data-link-variant` attribute on the `<a>` element. The theme provides CSS variables scoped to `[data-link-variant]` selectors.

### CSS Variables (Theme-provided)

The theme provides these CSS variables via `[data-link-variant]` selectors:

**Base Styles:**
- `--hs-link-color`: Text color
- `--hs-link-textDecoration`: Text decoration

**Hover States:**
- `--hs-link-color-hover`: Hover text color
- `--hs-link-textDecoration-hover`: Hover text decoration

**Active States:**
- `--hs-link-color-active`: Active text color (falls back to `--hs-link-color`)
- `--hs-link-textDecoration-active`: Active text decoration (falls back to `--hs-link-textDecoration`)

**Hardcoded Styles (not theme-configurable):**
- `display: inline-block`
- Focus outline: `2px solid currentColor` with `2px` offset

## Accessibility

The Link component follows accessibility best practices:

- **Semantic HTML**: Renders native `<a>` elements for proper browser behavior
- **Keyboard Navigation**: Full keyboard support via native link functionality
  - Enter key activates the link
  - Tab key moves focus to/from link
- **Link Security**:
  - Automatically uses `rel="noopener noreferrer"` with `target="_blank"` to prevent security vulnerabilities
  - Prevents new page from accessing `window.opener` object

## Best Practices

- **Use linkField prop when available**: If you have HubSpot field data, use the `linkField` prop instead of manually extracting href/target/rel
- **Do NOT mix approaches**: TypeScript will prevent you from using both `linkField` and `href` props together
- **Use variants for consistency**: Choose the appropriate variant (primaryLink/secondaryLink) rather than overriding colors directly
- **Security**: The component automatically adds `rel="noopener noreferrer"` when target is `_blank`
- **Minimal styling**: Keep link styling simple; use Button component for prominent CTAs

## Common Patterns

### Navigation Menu Item

```tsx
<Link href="/dashboard" variant="secondaryLink">
  Dashboard
</Link>
```

### External Resource

```tsx
<Link
  href="https://developers.hubspot.com"
  target="_blank"
>
  API Documentation
</Link>
```

### Image Wrapper

```tsx
<Link href="/product">
  <img src="product.jpg" alt="Product name" />
</Link>
```

## Related Components

- **Button**: Use for prominent CTAs and elements that need button-like visual styling

### Link vs Button Decision Tree

```
Need to make something clickable?
│
├─ Should it look like a button (prominent, styled)?
│  └─ Use Button component (even if it links to a URL)
│
└─ Should it be a simple link (minimal styling)?
   └─ Use Link component
```
