# Flex Component

A layout container component that implements the CSS Flexbox API for creating flexible, responsive layouts.

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

## Purpose

The Flex component provides a consistent interface for creating flexbox layouts in HubSpot CMS projects. It solves the common challenge of building responsive layouts by abstracting CSS flexbox properties into a declarative component API. Developers should use this component when they need to arrange child elements with flexible sizing, alignment, and spacing controls. The component supports all standard flexbox properties through props and allows customization via semantic HTML elements.

## Component Structure

```
Flex/
├── index.tsx                     # Main component with flexbox logic
├── types.ts                      # TypeScript type definitions for props
├── index.module.scss             # CSS module with design tokens
└── stories/
    ├── Flex.stories.tsx          # Component usage examples
    └── FlexDecorator.tsx         # Storybook decorator
```

## Components

### Flex (Main Component)

**Purpose:** Creates a flexbox container that controls the layout, alignment, and spacing of child elements.

**Props:**
```tsx
{
  as?: 'div' | 'span' | 'section' | 'article' | 'aside' | 'nav' | 'header' | 'footer' | 'main' | 'ul' | 'ol' | 'li';  // HTML element type (default: 'div')
  direction?: 'row' | 'row-reverse' | 'column' | 'column-reverse';  // Flex direction (default: 'row')
  wrap?: 'nowrap' | 'wrap' | 'wrap-reverse';  // Flex wrap behavior (default: 'nowrap')
  justifyContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';  // Main axis alignment (default: 'flex-start')
  alignItems?: 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch';  // Cross axis alignment (default: 'stretch')
  alignContent?: 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'stretch';  // Multi-line alignment (default: 'stretch')
  gap?: string;  // Spacing between flex items (e.g., '16px', '1rem')
  paddingInline?: string;  // Horizontal padding
  paddingBlock?: string;  // Vertical padding
  marginInline?: string;  // Horizontal margin
  marginBlock?: string;  // Vertical margin
  maxWidth?: string;  // Maximum width constraint
  maxHeight?: string;  // Maximum height constraint
  inline?: boolean;  // Use inline-flex instead of flex (default: false)
  className?: string;  // Additional CSS classes
  style?: CSSVariables;  // Inline styles and CSS variable overrides
  children?: React.ReactNode;  // Child elements
}
```

## Usage Examples

### Basic Horizontal Layout

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

<Flex direction="row" gap="16px">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</Flex>
```

### Vertical Stack

```tsx
<Flex direction="column" gap="24px">
  <div>Header</div>
  <div>Content</div>
  <div>Footer</div>
</Flex>
```

### Centered Content (With custom style)

```tsx
<Flex
  direction="row"
  justifyContent="center"
  alignItems="center"
  style={{ minHeight: '300px' }} // added for illustrative purposes
>
  <div>Centered Content</div>
</Flex>
```

### Space Between Layout

```tsx
<Flex
  direction="row"
  justifyContent="space-between"
  alignItems="center"
>
  <div>Left Item</div>
  <div>Right Item</div>
</Flex>
```

### Wrapped Grid Layout

```tsx
<Flex
  direction="row"
  wrap="wrap"
  gap="16px"
  maxWidth="800px"
>
  <div>Card 1</div>
  <div>Card 2</div>
  <div>Card 3</div>
  <div>Card 4</div>
  <div>Card 5</div>
</Flex>
```


### Semantic Article Layout

```tsx
<Flex
  as="article"
  direction="column"
  gap="32px"
  maxWidth="800px"
  marginInline="auto"
>
  <header>Article Title</header>
  <section>Article Content</section>
  <footer>Author Info</footer>
</Flex>
```

### Inline Flex Container

```tsx
<p>
  This is text with{' '}
  <Flex
    inline
    direction="row"
    gap="4px"
    alignItems="center"
  >
    <span>inline</span>
    <span>flex</span>
    <span>items</span>
  </Flex>
  {' '}in the flow.
</p>
```

## Styling

### CSS Variables

The Flex component uses CSS variables for all styling properties:

**Base Styles:**
- `--hscl-flex-display`: Display type (default: 'flex', or 'inline-flex' when inline=true)
- `--hscl-flex-direction`: Flex direction (default: 'row')
- `--hscl-flex-wrap`: Flex wrap behavior (default: 'nowrap')
- `--hscl-flex-justifyContent`: Main axis alignment (default: 'flex-start')
- `--hscl-flex-alignItems`: Cross axis alignment (default: 'stretch')
- `--hscl-flex-alignContent`: Multi-line alignment (default: 'stretch')
- `--hscl-flex-gap`: Gap between items
- `--hscl-flex-paddingInline`: Horizontal padding (default: 0)
- `--hscl-flex-paddingBlock`: Vertical padding (default: 0)
- `--hscl-flex-marginInline`: Horizontal margin (default: 0)
- `--hscl-flex-marginBlock`: Vertical margin (default: 0)
- `--hscl-flex-maxWidth`: Maximum width (default: 100%)
- `--hscl-flex-maxHeight`: Maximum height (default: auto)


## Accessibility

The Flex component supports accessibility best practices:

- **Semantic HTML**: The `as` prop allows rendering with appropriate semantic elements (nav, article, section, etc.) for better document structure
- **Keyboard Navigation**: Does not interfere with native keyboard navigation of child elements
- **Responsive Design**: Supports `wrap` property for responsive layouts that adapt to screen size

## Best Practices

- **Choose semantic elements**: Use the `as` prop to render the most appropriate HTML element (e.g., `as="nav"` for navigation, `as="article"` for article content)
- **Use gap instead of margins**: The `gap` property provides consistent spacing between flex items without margin collapsing issues
- **Set wrap for responsive layouts**: Use `wrap="wrap"` when items should flow to multiple lines on smaller screens
- **Use stretch for equal heights**: The default `alignItems="stretch"` creates equal-height columns
- **Combine with maxWidth**: Set `maxWidth` with `marginInline="auto"` for centered, constrained layouts
- **Use inline sparingly**: Only use `inline={true}` when the flex container needs to flow inline with text

## Grid vs Flex: When to Use Which

**Use Flex when:**
- You need a one-dimensional layout (either a row or column)
- Content size should determine item dimensions
- You want simple alignment and spacing between items
- Items should automatically adjust based on available space

**Use Grid when:**
- You need a two-dimensional layout (rows and columns together)
- You want precise control over item placement in both dimensions
- Creating structured layouts like galleries, dashboards, or forms
- You need items to align both horizontally and vertically

**Quick rule:** If your layout is primarily linear (items in a row or stacked vertically), use Flex. If you need both rows and columns working together, use Grid.

## Related Components

- **Button**: Often used as a child element within Flex layouts for action areas
- **Divider**: Can be used between Flex items to create visual separation
