# React Zoom Image Hover

A lightweight, performant React component that provides smooth image zoom on hover with customizable zoom behavior, touch support, and accessibility features.

## Features

- 🖼️ **Smooth Zoom Animation** - Smooth image zoom on hover with customizable scale and transition timing
- 📱 **Touch Support** - Works on mobile devices with touch gestures
- ♿ **Accessible** - Uses native `<img>` elements with proper alt text support for screen readers
- ⚡ **Performance Optimized** - Uses React hooks (`useCallback`, `useMemo`) and throttling for optimal performance
- 🎨 **Highly Customizable** - Extensive props for styling and behavior customization
- 🔍 **Smart Mouse Tracking** - Zoom follows mouse position with smooth, throttled updates
- 📦 **TypeScript Support** - Full TypeScript definitions included
- 🎯 **Zero Dependencies** - Only requires React as a peer dependency
- 🌐 **Semantic HTML** - Uses native `<img>` elements for better SEO and accessibility

## Installation

```bash
npm install react-zoom-image-hover
```

or

```bash
yarn add react-zoom-image-hover
```

## Preview

![Preview](/demo.gif)

## Basic Usage

```tsx
import Zoom from 'react-zoom-image-hover'

function App() {
	return <Zoom src='/path/to/image.jpg' width={400} height={300} zoomScale={2} alt='Product image' />
}
```

## Advanced Usage

```tsx
import Zoom from 'react-zoom-image-hover'

function ProductImage() {
	return (
		<Zoom
			src='https://example.com/product.jpg'
			width='100%'
			height={500}
			zoomScale={2.5}
			transitionTime={0.2}
			alt='Product detail view'
			className='product-image-container'
			innerClassName='product-image-inner'
			objectFit='cover'
			objectPosition='center'
			transitionTimingFunction='cubic-bezier(0.4, 0, 0.2, 1)'
			enableTouch={true}
			throttleDelay={16}
			style={{
				borderRadius: '8px',
				boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
			}}
		/>
	)
}
```

## Props

### Required Props

| Prop     | Type               | Description                                    |
| -------- | ------------------ | ---------------------------------------------- |
| `src`    | `string`           | Image source URL                               |
| `width`  | `string \| number` | Container width (CSS value: string or number)  |
| `height` | `string \| number` | Container height (CSS value: string or number) |

### Optional Props

| Prop                       | Type                                                       | Default      | Description                                                                                                                                                       |
| -------------------------- | ---------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `className`                | `string`                                                   | -            | Additional CSS class name for the container                                                                                                                       |
| `innerClassName`           | `string`                                                   | -            | Additional CSS class name for the inner image element                                                                                                             |
| `zoomScale`                | `number`                                                   | `1.5`        | Zoom scale multiplier                                                                                                                                             |
| `transitionTime`           | `number`                                                   | `0.1`        | Transition duration in seconds                                                                                                                                    |
| `style`                    | `CSSProperties`                                            | -            | Additional inline styles for the container                                                                                                                        |
| `alt`                      | `string`                                                   | -            | Alt text for accessibility (recommended)                                                                                                                          |
| `objectFit`                | `'contain' \| 'cover' \| 'fill' \| 'none' \| 'scale-down'` | `'contain'`  | CSS object-fit value - controls how the image is resized to fit its container. Use `contain` to fit entire image, `cover` to fill container, or `fill` to stretch |
| `objectPosition`           | `string`                                                   | `'center'`   | CSS object-position value - controls the position of the image within its container (e.g., `'center'`, `'top left'`, `'50% 30%'`)                                 |
| `enableTouch`              | `boolean`                                                  | `true`       | Enable touch support for mobile devices                                                                                                                           |
| `throttleDelay`            | `number`                                                   | `16`         | Throttle delay for mouse movement in milliseconds (~60fps)                                                                                                        |
| `transitionTimingFunction` | `string`                                                   | `'ease-out'` | CSS transition-timing-function value                                                                                                                              |

## TypeScript Support

The component is written in TypeScript and includes full type definitions. You can import the props interface:

```tsx
import Zoom, { ZoomProps } from 'react-zoom-image-hover'

const props: ZoomProps = {
	src: '/image.jpg',
	width: 400,
	height: 300,
}
```

## Performance

The component is optimized for performance:

- **Throttled Updates**: Mouse movement updates are throttled (configurable delay) to prevent excessive re-renders while maintaining smooth tracking
- **Memoized Styles**: Style objects are memoized with `useMemo` to avoid unnecessary recalculations
- **Optimized Callbacks**: Event handlers are wrapped in `useCallback` to prevent unnecessary child re-renders
- **Browser Optimization**: Uses `willChange: 'transform'` to hint the browser about upcoming transforms for better rendering performance
- **Efficient Position Calculation**: Mouse position is calculated relative to viewport, avoiding unnecessary scroll calculations

## Accessibility

The component is built with accessibility in mind:

- **Native `<img>` Elements** - Uses semantic HTML for better screen reader support
- **Alt Text Support** - Proper `alt` attribute support for image descriptions
- **Semantic Structure** - Clean, semantic HTML that's easy for assistive technologies to parse
- **Keyboard Friendly** - Works with keyboard navigation (inherits from container)

## Browser Support

Works in all modern browsers that support:

- CSS transforms and transitions
- CSS `object-fit` and `object-position` properties
- React 16+ (tested with React 16.8+ for hooks support)

## Examples

### E-commerce Product Image

```tsx
<Zoom
	src='/products/shoe.jpg'
	width={600}
	height={600}
	zoomScale={2}
	alt='Nike Air Max 90 - Side view'
	className='product-zoom'
	transitionTime={0.15}
/>
```

### Gallery with Custom Styling

```tsx
<Zoom
	src='/gallery/photo.jpg'
	width='100%'
	height={400}
	zoomScale={3}
	alt='Landscape photography'
	objectFit='cover'
	transitionTimingFunction='ease-in-out'
	style={{
		borderRadius: '12px',
		border: '2px solid #e0e0e0',
	}}
/>
```

### Mobile-Optimized

```tsx
<Zoom
	src='/mobile-image.jpg'
	width={300}
	height={300}
	zoomScale={2.5}
	enableTouch={true}
	throttleDelay={20}
	alt='Mobile optimized image'
/>
```

### Portrait Image with Custom Positioning

```tsx
<Zoom
	src='/portrait-photo.jpg'
	width={400}
	height={600}
	zoomScale={2.5}
	objectFit='contain'
	objectPosition='center'
	alt='Portrait photography'
	style={{
		borderRadius: '8px',
		border: '2px solid #ddd',
	}}
/>
```

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
