# 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
├── index.module.scss             # SCSS module with design tokens
└── stories/
    ├── Link.stories.tsx           # Storybook examples
    ├── LinkDecorator.tsx          # Storybook decorator
    └── LinkDecorator.module.scss  # 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
  };
  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')
  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>
  );
}
```

### 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>
```

## 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?: TLinkName` — field name (default: `'link'`). Generic `TLinkName extends string` lets consumers narrow the field-name literal for compile-time key matching on `fieldVisibility`.
- `linkDefault?` — default value for the LinkField
- `fieldVisibility?: Partial<Record<TLinkName, Visibility>>` — visibility options keyed by field name. Keys must match the `linkName` prop at compile time. Values match the cms-components Visibility schema (e.g. `hidden_subfields`, `controlling_field_path`, `operator`).

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

**Example — custom `linkName` (keys must match):**
```tsx
<Link.ContentFields
  linkName="footerLink"
  fieldVisibility={{ footerLink: { hidden_subfields: { no_follow: true } } }}
/>
```

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

### 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}>
      {fieldValues.linkText}
    </Link>
  );
}
```

**Manual (only when needed):**

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

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

## Styling

### CSS Variables (Theme-provided)

The component reads these CSS variables, which the theme is expected to provide:

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

**Hover / Focus States:**
- `--hs-section-link-color-hover`: Hover/focus text color
- `--hs-link-textDecoration-hover`: Hover/focus text decoration

**Hardcoded Styles (not theme-configurable):**
- `display: inline-block`
- `cursor: pointer`

The component itself does not declare a focus outline — the keyboard focus indicator is provided globally by the consuming theme's stylesheet (e.g. the focus-visible rule in `web-default-templates`'s `main.css`).

### Overriding link styles from consuming components

Because the component reads its styles from CSS custom properties, consumers can override them locally by setting the same vars on an ancestor element (or on the same element — e.g. `Logo` passes its class to `Link` so `.logo` ends up on the `<a>`). This is preferred over adding one-off selectors in the global theme.

```scss
.myWrapper {
  --hs-link-textDecoration: none;
  --hs-link-textDecoration-hover: none;
}
```

## 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
- **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">
  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
```
