import { Meta } from '@storybook/addon-docs/blocks';
import * as ClusterStories from './cluster.stories';

<Meta of={ClusterStories} title="Styles/Cluster" />

# Cluster Component Styles

Complete CSS reference for the Cluster layout primitive component.

## CSS Architecture

The Cluster component uses a **utility-class system** with CSS custom properties for theming. All spacing values use the unified spacing scale with fluid `clamp()` for responsive design.

**Key Characteristics:**
- **Zero Runtime:** All styling via CSS classes (no JavaScript)
- **Fluid Spacing:** CSS clamp() for responsive gaps without media queries
- **Rem Units:** All measurements in rem (1rem = 16px base)
- **CSS Variables:** Themable via CSS custom properties

## Base Styles

### `.cluster`

Base flexbox container with wrapping enabled.

```css
.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-sm); /* Default: clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem) */
}
```

**Default Behavior:**
- Displays items in a horizontal row
- Wraps items to next line when container width is exceeded
- Default gap: `--spacing-sm` (8-12px responsive)

## Gap Utilities

Control spacing between items using the unified spacing scale.

### `.cluster-gap-0`

Remove all gap spacing.

```css
.cluster-gap-0 {
  gap: 0;
}
```

**Usage:** `<Cluster gap="0">`
**Value:** `0`

### `.cluster-gap-xs`

Extra small gap spacing.

```css
.cluster-gap-xs {
  gap: var(--spacing-xs);
}
```

**Usage:** `<Cluster gap="xs">`
**Value:** `clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem)` (4-8px)
**Use Case:** Tight spacing for badges or compact tags

### `.cluster-gap-sm`

Small gap spacing.

```css
.cluster-gap-sm {
  gap: var(--spacing-sm);
}
```

**Usage:** `<Cluster gap="sm">`
**Value:** `clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem)` (8-12px)
**Use Case:** Default for tag clouds and keyword lists

### `.cluster-gap-md`

Medium gap spacing.

```css
.cluster-gap-md {
  gap: var(--spacing-md);
}
```

**Usage:** `<Cluster gap="md">`
**Value:** `clamp(0.75rem, 0.65rem + 0.45vw, 1.125rem)` (12-18px)
**Use Case:** Button groups and navigation links

### `.cluster-gap-lg`

Large gap spacing.

```css
.cluster-gap-lg {
  gap: var(--spacing-lg);
}
```

**Usage:** `<Cluster gap="lg">`
**Value:** `clamp(1rem, 0.85rem + 0.6vw, 1.5rem)` (16-24px)
**Use Case:** Spacious navigation or large buttons

### `.cluster-gap-xl`

Extra large gap spacing.

```css
.cluster-gap-xl {
  gap: var(--spacing-xl);
}
```

**Usage:** `<Cluster gap="xl">`
**Value:** `clamp(1.5rem, 1.25rem + 0.75vw, 2rem)` (24-32px)
**Use Case:** Very spacious layouts with large items

## Justify Utilities

Control horizontal alignment of items (justify-content).

### `.cluster-justify-start`

Align items to the start (left in LTR).

```css
.cluster-justify-start {
  justify-content: flex-start;
}
```

**Usage:** `<Cluster justify="start">`
**Behavior:** Items aligned to left (or right in RTL)

### `.cluster-justify-center`

Center items horizontally.

```css
.cluster-justify-center {
  justify-content: center;
}
```

**Usage:** `<Cluster justify="center">`
**Behavior:** Items centered horizontally within container
**Use Case:** Centered tag clouds or navigation

### `.cluster-justify-end`

Align items to the end (right in LTR).

```css
.cluster-justify-end {
  justify-content: flex-end;
}
```

**Usage:** `<Cluster justify="end">`
**Behavior:** Items aligned to right (or left in RTL)
**Use Case:** Right-aligned action buttons

### `.cluster-justify-between`

Distribute items with space between.

```css
.cluster-justify-between {
  justify-content: space-between;
}
```

**Usage:** `<Cluster justify="between">`
**Behavior:** First item at start, last item at end, equal space between
**Use Case:** Distributed navigation links

## Align Utilities

Control vertical alignment of items within each row (align-items).

### `.cluster-align-start`

Align items to the top of the row.

```css
.cluster-align-start {
  align-items: flex-start;
}
```

**Usage:** `<Cluster align="start">`
**Behavior:** Items aligned to top of the row
**Use Case:** Items with varying heights

### `.cluster-align-center`

Center items vertically within the row.

```css
.cluster-align-center {
  align-items: center;
}
```

**Usage:** `<Cluster align="center">`
**Behavior:** Items centered vertically within row
**Use Case:** Mixed content (icons + text)

### `.cluster-align-end`

Align items to the bottom of the row.

```css
.cluster-align-end {
  align-items: flex-end;
}
```

**Usage:** `<Cluster align="end">`
**Behavior:** Items aligned to bottom of the row

### `.cluster-align-baseline`

Align items by their text baseline.

```css
.cluster-align-baseline {
  align-items: baseline;
}
```

**Usage:** `<Cluster align="baseline">`
**Behavior:** Text baselines aligned across items
**Use Case:** Navigation links or text-based buttons

## CSS Custom Properties

### Global Spacing Scale

Defined in `_globals.scss`:

```scss
:root {
  --spacing-0: 0;
  --spacing-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem);   /* 4-8px */
  --spacing-sm: clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem);  /* 8-12px */
  --spacing-md: clamp(0.75rem, 0.65rem + 0.45vw, 1.125rem); /* 12-18px */
  --spacing-lg: clamp(1rem, 0.85rem + 0.6vw, 1.5rem);      /* 16-24px */
  --spacing-xl: clamp(1.5rem, 1.25rem + 0.75vw, 2rem);     /* 24-32px */
}
```

### Theming

Override spacing scale globally:

```css
:root {
  /* Custom spacing for larger gaps */
  --spacing-md: 1.5rem;
  --spacing-lg: 2rem;
}
```

Or per component:

```tsx
<Cluster
  gap="md"
  styles={{
    '--spacing-md': '2rem',
  } as React.CSSProperties}
>
  <Tag>React</Tag>
</Cluster>
```

## Responsive Behavior

### Fluid Spacing

Gap values automatically adjust based on viewport width using CSS clamp():

```
Viewport Width → Gap Size
320px (mobile)  → Minimum (e.g., 0.5rem for sm)
~800px (tablet) → Middle value (interpolated)
1280px+ (desktop) → Maximum (e.g., 0.75rem for sm)
```

**No media queries needed!** The spacing scales smoothly between min and max values.

### Wrapping Behavior

Items automatically wrap to the next line when:
- Container width is insufficient for all items
- Sum of item widths + gaps exceeds container width

**Example:**

```
Container: 600px
Items: 8 buttons (120px each)
Gap: 1rem (16px)

Row 1: 4 buttons (120 × 4 = 480px) + (16 × 3 = 48px gaps) = 528px ✓
Row 2: 4 buttons (wraps to next line)
```

## Class Generation

The Cluster component generates classes based on props:

```tsx
<Cluster gap="md" justify="center" align="baseline">
  Content
</Cluster>
```

**Generated classes:**
```html
<div class="cluster cluster-gap-md cluster-justify-center cluster-align-baseline">
  Content
</div>
```

## Combining with Custom Styles

### Custom Classes

```tsx
<Cluster className="custom-cluster" gap="sm">
  <Tag>React</Tag>
</Cluster>

<style>
  .custom-cluster {
    max-width: 40rem; /* 640px */
    margin-inline: auto;
    padding: 1rem;
    background: var(--bg-subtle, #f9f9f9);
    border-radius: 0.5rem;
  }
</style>
```

### Inline Styles

```tsx
<Cluster
  gap="md"
  styles={{
    maxWidth: '600px',
    marginInline: 'auto',
    padding: '1.5rem',
  }}
>
  <Button>Action 1</Button>
  <Button>Action 2</Button>
</Cluster>
```

## SCSS Source

**File:** `src/components/cluster/cluster.scss`

```scss
/**
 * Cluster Component Styles
 *
 * Utility classes for the Cluster layout primitive.
 * Provides wrapping flex layout for inline groups (tags, badges, buttons).
 * All spacing values use the unified spacing scale from globals.
 * All units are in rem (1rem = 16px base).
 */

// ============================================================================
// Base Cluster
// ============================================================================

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-sm); // Default small gap for inline items
}

// ============================================================================
// Gap Utilities
// ============================================================================

.cluster-gap-0 {
  gap: 0;
}

.cluster-gap-xs {
  gap: var(--spacing-xs);
}

.cluster-gap-sm {
  gap: var(--spacing-sm);
}

.cluster-gap-md {
  gap: var(--spacing-md);
}

.cluster-gap-lg {
  gap: var(--spacing-lg);
}

.cluster-gap-xl {
  gap: var(--spacing-xl);
}

// ============================================================================
// Justify Utilities (Horizontal Alignment)
// ============================================================================

.cluster-justify-start {
  justify-content: flex-start;
}

.cluster-justify-center {
  justify-content: center;
}

.cluster-justify-end {
  justify-content: flex-end;
}

.cluster-justify-between {
  justify-content: space-between;
}

// ============================================================================
// Align Utilities (Vertical Alignment)
// ============================================================================

.cluster-align-start {
  align-items: flex-start;
}

.cluster-align-center {
  align-items: center;
}

.cluster-align-end {
  align-items: flex-end;
}

.cluster-align-baseline {
  align-items: baseline;
}
```

## Compiled CSS Output

**Location:** `libs/components/cluster/cluster.css`

The SCSS is compiled to compressed CSS:

```css
.cluster{display:flex;flex-wrap:wrap;gap:var(--spacing-sm)}.cluster-gap-0{gap:0}.cluster-gap-xs{gap:var(--spacing-xs)}.cluster-gap-sm{gap:var(--spacing-sm)}.cluster-gap-md{gap:var(--spacing-md)}.cluster-gap-lg{gap:var(--spacing-lg)}.cluster-gap-xl{gap:var(--spacing-xl)}.cluster-justify-start{justify-content:flex-start}.cluster-justify-center{justify-content:center}.cluster-justify-end{justify-content:flex-end}.cluster-justify-between{justify-content:space-between}.cluster-align-start{align-items:flex-start}.cluster-align-center{align-items:center}.cluster-align-end{align-items:flex-end}.cluster-align-baseline{align-items:baseline}
```

**Minified Size:** ~400 bytes (gzipped: ~200 bytes)

## Performance

### Bundle Size
- **SCSS Source:** 1.8 KB
- **Compiled CSS:** 0.4 KB
- **Gzipped:** 0.2 KB

### Runtime Performance
- **Zero JavaScript:** All layout via CSS
- **No Re-renders:** Static utility classes
- **GPU Accelerated:** Flexbox handled by browser compositor

### Loading Strategy
- **Critical CSS:** Include `.cluster` base class
- **Lazy Load:** Load gap/justify/align utilities on demand

## Browser Support

| Feature | Chrome | Firefox | Safari | Edge |
|---------|--------|---------|--------|------|
| Flexbox | ✅ 29+ | ✅ 28+ | ✅ 9+ | ✅ 12+ |
| flex-wrap | ✅ 29+ | ✅ 28+ | ✅ 9+ | ✅ 12+ |
| gap (flexbox) | ✅ 84+ | ✅ 63+ | ✅ 14.1+ | ✅ 84+ |
| CSS clamp() | ✅ 79+ | ✅ 75+ | ✅ 13.1+ | ✅ 79+ |

**Fallback:** For browsers without flexbox gap support, use margin on child elements.

## Accessibility

### Semantic HTML

Use appropriate elements via the `as` prop:

```tsx
<Cluster as="nav">     {/* <nav> for navigation */}
<Cluster as="ul">      {/* <ul> for lists */}
<Cluster as="section"> {/* <section> for grouped content */}
```

### Focus Order

Flexbox maintains DOM order for keyboard navigation:

```tsx
<Cluster gap="md">
  <button>First</button>   {/* Tab order: 1 */}
  <button>Second</button>  {/* Tab order: 2 */}
  <button>Third</button>   {/* Tab order: 3 */}
</Cluster>
```

Even when wrapped, focus order follows DOM structure.

### Screen Readers

Provide ARIA labels for non-semantic containers:

```tsx
<Cluster aria-label="Technology tags">
  <Tag>React</Tag>
  <Tag>TypeScript</Tag>
</Cluster>
```

## Migration from Legacy Styles

### From Inline Flex

**Before:**
```css
.tag-cloud {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 8px;
}
```

**After:**
```tsx
<Cluster gap="sm" className="tag-cloud">
  <Tag>React</Tag>
</Cluster>
```

### From Float Layouts

**Before:**
```css
.tags {
  overflow: auto; /* Clearfix */
}

.tags > * {
  float: left;
  margin-right: 8px;
  margin-bottom: 8px;
}
```

**After:**
```tsx
<Cluster gap="sm">
  <Tag>React</Tag>
</Cluster>
```

### From Grid with Auto-Fill

**Before:**
```css
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 1rem;
}
```

**After (if items have varying widths):**
```tsx
<Cluster gap="md">
  <Button>Short</Button>
  <Button>Medium Length</Button>
  <Button>Very Long Button Text</Button>
</Cluster>
```

## Related Documentation

- **README.mdx** - Component usage and patterns
- **cluster.stories.tsx** - Interactive examples
- **cluster.test.tsx** - Unit tests and behavior
- **_globals.scss** - Global spacing scale definitions

## Version History

- **v0.5.11** - Initial release of Cluster component
  - Unified spacing scale
  - Gap, justify, and align utilities
  - Polymorphic `as` prop
  - TypeScript types and comprehensive tests

## Resources

- **Flexbox Guide:** [MDN Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout)
- **CSS clamp():** [MDN clamp()](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp)
- **Spacing Scale:** See `_globals.scss` for complete scale
- **Component Composition:** See README.mdx for patterns

## License

MIT
