useTransform
July 29, 2026 · View on GitHub
A context-based transform accumulation system. TransformProvider tracks programmatic transforms (translate, rotate, scale) and propagates them down the component tree. useTransform lets child components read the accumulated transform or react to changes.
The primary use case is scroll trigger compensation — when a parent element is translated programmatically (e.g., parallax), child useScrollTrigger hooks need to know about that offset to compute accurate progress values.
Usage
import { useRef } from 'react'
import { TransformProvider, useTransform } from 'hamo'
import type { TransformRef } from 'hamo'
function ParallaxSection() {
const transformRef = useRef<TransformRef>(null)
// Set transforms imperatively (e.g., from a scroll callback)
function onScroll(y) {
transformRef.current?.setTranslate(0, y)
}
return (
<TransformProvider ref={transformRef}>
<ChildComponent />
</TransformProvider>
)
}
function ChildComponent() {
// Read accumulated transform from all parent providers
const getTransform = useTransform()
const { translate } = getTransform()
// translate.y reflects the parent's offset
// Or react to changes:
useTransform((transform) => {
console.log('Parent moved to:', transform.translate.y)
})
return <div>Content</div>
}
TransformProvider
Wraps a subtree with a transform context. Nested providers accumulate transforms:
- Translate and rotate: additive
- Scale: multiplicative
Props
children: (ReactNode) Child components.ref: (Ref<TransformRef>) Optional imperative handle.
TransformRef Methods
setTranslate(x?, y?, z?)— Set translation (defaults: 0).setRotate(x?, y?, z?)— Set rotation in degrees (defaults: 0).setScale(x?, y?, z?)— Set scale (defaults: 1).
useTransform
Without callback
Returns a getTransform() function to read the current accumulated transform on demand.
const getTransform = useTransform()
const { translate, rotate, scale } = getTransform()
With callback
Registers a callback that fires whenever any ancestor TransformProvider updates its transform.
useTransform((transform) => {
element.style.transform = `translateY(${transform.translate.y}px)`
})
Parameters
callback: (function, optional) Fired with the accumulatedTransformon every change.deps: (array, default:[]) Dependencies for the callback effect.
Return Value
Returns getTransform — a function that returns the current accumulated Transform.
Transform Type
type Transform = {
translate: { x: number; y: number; z: number }
rotate: { x: number; y: number; z: number }
scale: { x: number; y: number; z: number }
}
Example: Nested Providers
import { useRef } from 'react'
import { TransformProvider, useTransform } from 'hamo'
import type { TransformRef } from 'hamo'
function Outer() {
const ref = useRef<TransformRef>(null)
ref.current?.setTranslate(0, 100) // y = 100
return (
<TransformProvider ref={ref}>
<Inner />
</TransformProvider>
)
}
function Inner() {
const ref = useRef<TransformRef>(null)
ref.current?.setTranslate(0, 50) // y = 50
return (
<TransformProvider ref={ref}>
<Leaf />
</TransformProvider>
)
}
function Leaf() {
const getTransform = useTransform()
const { translate } = getTransform()
// translate.y === 150 (100 + 50, accumulated from both parents)
}