> ## Documentation Index
> Fetch the complete documentation index at: https://sunpeak.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Utility Functions

> Utility functions exported by sunpeak: cn() for class name merging, and media query helpers for motion, touch, and hover detection.

<Badge color="yellow">sunpeak API</Badge>

## cn

Merges class names using [clsx](https://github.com/lukeed/clsx) and [tailwind-merge](https://github.com/dcastil/tailwind-merge). Handles conditional classes, arrays, and deduplicates conflicting Tailwind utilities.

### Import

```tsx theme={null}
import { cn } from 'sunpeak';
```

### Signature

```tsx theme={null}
function cn(...inputs: ClassValue[]): string
```

### Usage

```tsx theme={null}
import { cn } from 'sunpeak';

function Card({ active, className }: { active: boolean; className?: string }) {
  return (
    <div className={cn(
      'rounded-lg p-4 border',
      active && 'border-blue-500 bg-blue-50',
      className,
    )}>
      ...
    </div>
  );
}
```

***

## prefersReducedMotion

Returns `true` if the user has enabled the "reduce motion" accessibility setting.

### Import

```tsx theme={null}
import { prefersReducedMotion } from 'sunpeak';
```

### Signature

```tsx theme={null}
function prefersReducedMotion(): boolean
```

### Usage

```tsx theme={null}
import { prefersReducedMotion } from 'sunpeak';

function AnimatedCard() {
  const style = prefersReducedMotion()
    ? {}
    : { transition: 'transform 0.3s ease' };

  return <div style={style}>...</div>;
}
```

***

## isPrimarilyTouchDevice

Returns `true` if the primary input mechanism is coarse (touch). Checks the `(pointer: coarse)` media query.

### Import

```tsx theme={null}
import { isPrimarilyTouchDevice } from 'sunpeak';
```

### Signature

```tsx theme={null}
function isPrimarilyTouchDevice(): boolean
```

### Usage

```tsx theme={null}
import { isPrimarilyTouchDevice } from 'sunpeak';

function InteractiveMap() {
  const touchMode = isPrimarilyTouchDevice();

  return (
    <div onPointerDown={touchMode ? handleTouchStart : handleMouseStart}>
      ...
    </div>
  );
}
```

<Tip>
  For host-reported device capabilities, use [`useDeviceCapabilities`](/app-framework/hooks/use-device-capabilities) which reads the `touch` and `hover` values from the host context.
</Tip>

***

## isHoverAvailable

Returns `true` if the primary input mechanism supports hover. Checks the `(hover: hover)` media query.

### Import

```tsx theme={null}
import { isHoverAvailable } from 'sunpeak';
```

### Signature

```tsx theme={null}
function isHoverAvailable(): boolean
```

### Usage

```tsx theme={null}
import { isHoverAvailable } from 'sunpeak';

function Tooltip({ children, text }: { children: ReactNode; text: string }) {
  if (!isHoverAvailable()) {
    // On touch devices, show tooltip inline instead
    return <>{children}<span className="text-xs ml-1">{text}</span></>;
  }

  return (
    <div className="group relative">
      {children}
      <span className="hidden group-hover:block absolute ...">{text}</span>
    </div>
  );
}
```
