# HubSpot CMS Component Library

A collection of React components designed exclusively for building HubSpot CMS modules. These components provide pre-built UI elements with integrated HubSpot field definitions, CSS module styling, and TypeScript support.

## Installation

```bash
npm install @hubspot/cms-component-library
```

## Important Context

**HubSpot CMS Only**: These components are designed specifically for use within HubSpot's CMS environment when building modules. They depend on HubSpot-specific packages (`@hubspot/cms-components`) and will not work in standard React applications outside of the HubSpot CMS.

## Component Architecture

Each component follows a consistent structure:

```
ComponentName/
├── index.tsx                 # Main component (default export)
├── types.ts                  # TypeScript type definitions
├── ContentFields.tsx         # HubSpot content field definitions
├── StyleFields.tsx           # HubSpot style field definitions
├── index.module.scss         # CSS module styles with design tokens
└── stories/                  # Storybook documentation
```

## Importing Components

### Default Component Export

All components are exported as default exports and imported using the component name as the path:

```tsx
import Component from '@hubspot/cms-component-library/ComponentName'
```

### Components with Sub-Components

Some higher-order components export named sub-components for composition patterns:

```tsx
import Component, {
  SubComponent1,
  SubComponent2,
  SubComponent3
} from '@hubspot/cms-component-library/CompoundComponent';
```

## Field Definitions

Most components attach HubSpot CMS field definitions as static properties for easy integration with modules.

### ContentFields

Define the content-related fields (text, images, links, etc.) that editors can configure:

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

// In your module's fields definition:
export function fields() {
  return (
    <>
      <Button.ContentFields
        buttonTextLabel="CTA text"
        buttonTextName="ctaText"
        buttonTextDefault="Get Started"
      />
    </>
  );
}
```

### StyleFields

Define styling-related fields (variants, colors, spacing) that editors can configure:

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

// In your module's fields definition:
export function fields() {
  return (
    <>
      <Button.StyleFields
        buttonVariantLabel="Button style"
        buttonVariantName="buttonStyle"
        buttonVariantDefault="primary"
      />
    </>
  );
}
```

### Combined Usage

Typically, you'll use both ContentFields and StyleFields together:

```tsx
import { FieldGroup, ModuleFields } from '@hubspot/cms-components/fields';
import Button from '@hubspot/cms-component-library/Button';
import Text from '@hubspot/cms-component-library/Text';

export const fields = (
  <ModuleFields>
    <Text.ContentFields textFeatureSet="heading" />
    <Button.ContentFields />
    <FieldGroup label="Style" name="style" tab="STYLE">
      <Button.StyleFields />
    </FieldGroup>
  </ModuleFields>
);
```

## Consuming Components in Modules

### Basic Module Example

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

export const Component = ({ buttonVariant, buttonLink, buttonText }) => {
  return (
    <>
      <Text fieldPath="text" />

      <Button
        buttonType="link"
        href={buttonLink?.url?.href}
        variant={buttonVariant}
      >
        {buttonText}
      </Button>
    </>
  );
};

export { fields } from './fields';

export const meta: ModuleMeta = {
  label: 'Button',
  content_types: [],
  icon: '',
  categories: ['content'],
};
```

### Using Layout Components

Layout components like Flex and Grid help organize other components:

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

export const Component = () => {
  return (
    <Flex
      direction="column"
      gap="1rem"
      alignItems="center"
    >
      <Button buttonType="link" href="/page1">
        Page 1
      </Button>
      <Button buttonType="link" href="/page2">
        Page 2
      </Button>
    </Flex>
  );
};
```

## Interactive Components and Islands

Interactive components that require client-side JavaScript are pre-wrapped with the necessary island context. You can use them directly without additional island wrapping:

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

// No need to wrap in an island - the component is already exported with island context
export const Component = () => {
  return (
    <InteractiveComponent
      onClick={() => console.log('clicked')}
    />
  );
};
```

## Component Composition Patterns

## Field Configuration Props

ContentFields and StyleFields accept configuration props to customize field labels, names, and defaults:

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

export function fields() {
  return (
    <>
      <Button.ContentFields
        buttonTextLabel="Call to Action text"
        buttonTextName="ctaText"
        buttonTextDefault="Start Free Trial"
        buttonLinkLabel="CTA destination"
        buttonLinkName="ctaLink"
        showButtonLink={true}
        iconLabel="CTA icon"
        showIconLabel="Display icon?"
        showIconDefault={false}
      />

      <Button.StyleFields
        buttonVariantLabel="CTA style"
        buttonVariantName="ctaStyle"
        buttonVariantDefault="primary"
      />
    </>
  );
}
```

## Best Practices

1. **Import only what you need**: Import specific components rather than the entire library
2. **Use field definitions**: Leverage ContentFields and StyleFields for editor-friendly modules
3. **CSS Variables over inline styles**: Prefer CSS custom properties for styling customization
4. **Semantic HTML**: Components render semantic HTML elements for accessibility
5. **TypeScript types**: Use provided TypeScript types for type safety
6. **Layout composition**: Use Flex and Grid for responsive layouts rather than custom CSS
