# Logo Component

A responsive logo component that displays brand logos from HubSpot brand settings with optional link wrapping, size constraints, and loading optimization.

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

## Purpose

The Logo component automatically integrates with HubSpot's brand settings to display the primary brand logo. It handles responsive image rendering, optional link wrapping for navigation, size constraints for different layout contexts (navigation bars, footers, headers), and loading optimization. This component eliminates the need to manually configure logo images across modules and ensures brand consistency throughout the site.

## Component Structure

```
Logo/
├── index.tsx                   # Main component with render logic
├── types.tsx                   # TypeScript type definitions
├── ContentFields.tsx           # HubSpot CMS field definitions
├── index.module.scss           # CSS module with design tokens
├── _dummyLogoData.ts           # Test data for development
└── assets/
    └── hubspot-logo.png        # Default dummy logo asset
```

## Props

```tsx
{
  useDummyLogo?: boolean;       // Use test logo instead of brand settings (development only)
  companyName?: string;         // Fallback text displayed when no brand logo src is available
  className?: string;           // Additional CSS classes
  style?: React.CSSProperties;  // Inline styles
  maxWidth?: string;            // Maximum width constraint (e.g., "150px", "10rem", "50%")
  maxHeight?: string;           // Maximum height constraint (e.g., "50px", "5rem", "10vh")
  loading?: 'lazy' | 'eager' | 'disabled';  // Image loading behavior (defaults to 'eager')
}
```

**Fallback Behavior:** When no brand logo `src` is available and `companyName` is provided, the component renders the company name as styled text instead of returning nothing. If a logo `src` is present, the logo image is always displayed and `companyName` is ignored. If neither a logo `src` nor `companyName` is provided, the component renders nothing.

**Note:** The Logo component does not accept `width` or `height` props directly. The intrinsic dimensions come from the brand settings logo data (`LogoData.width` and `LogoData.height`), which are used to set the image's intrinsic size via the `width` and `height` attributes on the `<img>` element. If no `maxWidth` or `maxHeight` props are provided, the logo will display at its intrinsic size from brand settings (constrained by responsive CSS to a maximum of 100% of the container width). Use `maxWidth` and `maxHeight` to constrain the display size while maintaining the logo's aspect ratio. Both props accept any valid CSS dimension value (pixels, rem, percentages, viewport units, etc.).

**Brand Settings Data Structure:**
The component uses `useBrandSettings()` which returns logo data in this format:
```tsx
{
  src: string;        // Logo image URL
  alt?: string;       // Alt text for accessibility
  width?: number;     // Intrinsic width in pixels (sets image width attribute; establishes initial size when no maxWidth/maxHeight provided)
  height?: number;    // Intrinsic height in pixels (sets image height attribute; establishes initial size when no maxWidth/maxHeight provided)
  link?: string;      // Optional URL for logo link
}
```

## Usage Examples

### Basic Logo

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

<Logo />
```

### Logo in Navigation Bar

When you need to constrain logo size in a navigation header:

```tsx
<nav>
  <Logo maxWidth="120px" />
  {/* Navigation items */}
</nav>
```

### Company Name Fallback

When no brand logo is configured, display the company name instead:

```tsx
<Logo companyName="Acme Corporation" />
```

### Logo with Lazy Loading

For logos that appear below the fold:

```tsx
<Logo
  loading="lazy"
  maxWidth="150px"
/>
```

### Height-Only Constraint

When you only need to constrain the height (e.g., in a navigation bar with fixed height), use `maxHeight` alone. The component automatically maintains the aspect ratio:

```tsx
<nav>
  <Logo maxHeight="50px" />
  {/* Navigation items */}
</nav>
```

**Special Behavior:** When only `maxHeight` is provided (without `maxWidth`), the component automatically:
- Sets `maxInlineSize` to `fit-content` via inline style
- Sets the image's `inlineSize` and `blockSize` to `auto`
- This ensures the logo maintains its natural aspect ratio while respecting the height constraint, allowing the width to scale proportionally

### Custom Sizing

Constrain logo size using both maxWidth and maxHeight while maintaining aspect ratio:

```tsx
<Logo
  maxWidth="250px"
  maxHeight="80px"
/>
```

### Local Development Testing

When testing locally on the dev server where brand settings aren't available, use test data:

```tsx
<Logo useDummyLogo={true} maxWidth="150px" />
```

## HubSpot CMS Integration

### Brand Settings Integration

The Logo component automatically retrieves logo data from HubSpot brand settings using the `useBrandSettings()` hook from `@hubspot/cms-components`. While this hook provides access to multiple logos, this component specifically uses only the primary logo configured in the HubSpot brand kit settings.

### Module Usage Example

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

export default function HeaderModule({ fieldValues }) {
  return (
    <header>
      <Logo
        maxWidth={fieldValues.logoMaxWidth}
        loading="eager"
      />
      <nav>{/* Navigation items */}</nav>
    </header>
  );
}
```

### Field Configuration

The Logo component exposes a `ContentFields` sub-component (`Logo.ContentFields`) that adds a HubSpot CMS `LogoField` to a module. Use this when you want editors to override the brand-settings logo on a per-module basis.

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

// Inside your module's Fields export:
<Logo.ContentFields />
```

`Logo.ContentFields` accepts the following props (all optional):

```tsx
{
  logoLabel?: string;   // Field label shown in editor (default: 'Logo')
  logoName?: string;    // Field name used for fieldValues lookup (default: 'img')
  logoDefault?: {       // Default field values
    override_inherited_src?: boolean;  // default: false
    src?: string | null;               // default: null
    alt?: string | null;               // default: null
    loading?: string;                  // default: 'disabled'
  };
  showLoading?: boolean;  // Show loading selector in editor (default: true)
}
```

When `ContentFields` is not used, all logo data comes from HubSpot brand settings via the `useBrandSettings()` hook automatically.

## Styling

The Logo component applies layout properties as inline styles via props. The `style` prop accepts standard `React.CSSProperties` for additional customization.

**Base defaults (from CSS module):**
- `display: inline-block`
- `inline-size: fit-content`
- `max-inline-size: 100%`
- `max-block-size: none`

The `.logo` wrapper also sets `--hs-link-textDecoration: none` and `--hs-link-textDecoration-hover: none` to suppress underlines when the logo is wrapped in a link.

These defaults are overridden when `maxWidth` or `maxHeight` props are provided.

**Company Name Fallback:**
- The company name fallback text uses `font-size: 28px`, `font-weight: 700`, `color: currentColor`, `white-space: nowrap`, and inherits the heading font family via `var(--hs-headings-fontFamily, sans-serif)`.

## Accessibility

The Logo component follows accessibility best practices:

- **Alt Text**: Uses alt text from brand settings for screen readers. Always provide meaningful alt text in your brand settings (e.g., "Company Name Logo" rather than just "Logo")
- **Semantic Links**: When a link is configured in brand settings, the logo automatically wraps in a semantic `<Link>` component with proper accessibility attributes
- **Keyboard Navigation**: Focus states are clearly visible with customizable outline styles for keyboard users
- **Image Loading**: The `loading` prop allows control over image loading behavior, preventing layout shifts that can confuse assistive technology users
- **Responsive Images**: Uses the Image component internally to provide responsive image handling for better performance across devices

## Best Practices

### Brand Settings Configuration
- **Data source**: Logo data comes from HubSpot brand settings via the `useBrandSettings()` hook. If logo data is not showing up correctly, check the brand settings configuration first
- **Alt text**: The component uses alt text from brand settings. If accessibility issues arise, verify that meaningful alt text (e.g., "Acme Corporation Logo") is configured in brand settings rather than generic text
- **Logo linking**: The component automatically wraps the logo in a link if a link URL is configured in brand settings. If linking behavior is unexpected, check the brand settings link configuration
- **Image quality**: Logo display quality depends on the image uploaded to brand settings. For debugging display issues, verify that appropriately sized images (recommended 2x resolution for retina displays) are configured

### Size Constraints
- **Use maxWidth in constrained layouts**: Navigation bars and footers often need size limits to maintain layout integrity
- **Use maxHeight for height-only constraints**: When you only need to constrain height, the component automatically handles width sizing to maintain aspect ratio
- **Maintain aspect ratio**: The component preserves the logo's aspect ratio from brand settings. Use `maxWidth` and `maxHeight` together to constrain both dimensions, or use one alone to constrain a single dimension
- **Consider responsive breakpoints**: Use the style prop with media queries for responsive sizing

### Performance
- **Use eager loading for above-the-fold logos**: Navigation logos should load immediately (`loading="eager"`)
- **Use lazy loading for below-the-fold logos**: Footer or secondary logos can use `loading="lazy"` to improve initial page load
- **Optimize source images**: Ensure logos in brand settings are appropriately sized and compressed

### Development
- **Use useDummyLogo only in development**: This prop is for testing and should not be used in production code
- **Test with real brand settings**: Always test your modules with actual brand settings before deployment

### Layout Integration
- **Combine with navigation components**: Logos commonly appear alongside navigation menus in headers
- **Provide adequate spacing**: Use CSS margins or padding to ensure the logo has breathing room
- **Consider dark/light themes**: If your site has theme variations, test logo visibility in both contexts

## Integration with Other Components

The Logo component internally uses:

- **Image Component**: For responsive image rendering with proper attributes
- **Link Component**: For accessible link wrapping when logo.link is configured

This ensures consistency with other components in the library and leverages shared functionality for images and navigation.

## Performance Considerations

### Loading Behavior
- `loading="eager"`: Image loads immediately (default) - use for critical above-the-fold logos
- `loading="lazy"`: Image loads when near viewport - use for below-the-fold logos to improve initial page load

### Responsive Images
The component uses the Image component internally, which handles:
- Responsive image sizing based on container
- Proper aspect ratio maintenance
- Efficient loading strategies

## Common Use Cases

### Navigation Header
```tsx
<header style={{ display: 'flex', alignItems: 'center', padding: '1rem' }}>
  <Logo maxHeight="50px" loading="eager" />
  <nav>{/* Navigation menu */}</nav>
</header>
```

### Footer Branding
```tsx
<footer style={{ padding: '2rem', backgroundColor: '#f5f5f5' }}>
  <Logo maxWidth="180px" loading="lazy" />
  <p>© 2026 Company Name. All rights reserved.</p>
</footer>
```

### Centered Hero Logo
```tsx
<section style={{ textAlign: 'center', padding: '4rem' }}>
  <Logo
    maxWidth="300px"
    style={{ display: 'block', margin: '0 auto' }}
  />
  <h1>Welcome to Our Site</h1>
</section>
```

### Sidebar Logo
```tsx
<aside>
  <Logo
    maxWidth="100px"
    style={{ display: 'block' }}
  />
  {/* Sidebar content */}
</aside>
```
