Motion
인터랙션 훅
stable호버, 클릭, 포커스, 키보드 이벤트에 반응하는 인터랙션 모션 훅
@hua-labs/motion-corev2.0.0
Import
import {
useHoverMotion,
useClickToggle,
useFocusToggle,
useButtonEffect,
useInteractive,
useKeyboardToggle,
} from '@hua-labs/motion-core'useHoverMotion
마우스 호버 시 스케일, 이동, 투명도 변화를 애니메이션한다.
Signature
function useHoverMotion<T extends MotionElement = HTMLDivElement>(
options?: HoverMotionOptions
): BaseMotionReturn<T> & { isHovered: boolean }Parameters
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
hoverScale | number | 프로필 기본값 | 호버 시 스케일 |
hoverY | number | 프로필 기본값 | 호버 시 Y 오프셋 (px) |
hoverOpacity | number | 1 | 호버 시 투명도 |
duration | number | 프로필 기본값 | 전환 지속 시간 (ms) |
easing | string | 프로필 기본값 | CSS 이징 |
Returns
| 이름 | 타입 | 설명 |
|---|---|---|
ref | RefObject<T> | DOM 요소 참조 |
style | MotionStyle | 적용할 CSS 스타일 |
isHovered | boolean | 현재 호버 여부 |
isAnimating | boolean | 애니메이션 진행 여부 |
Usage
import { useHoverMotion } from '@hua-labs/motion-core'
function HoverCard() {
const { ref, style, isHovered } = useHoverMotion({
hoverScale: 1.05,
hoverY: -4,
duration: 200
})
return (
<div ref={ref} style={style}>
{isHovered ? '호버 중' : '호버해 보세요'}
</div>
)
}useClickToggle
클릭, 더블클릭, 우클릭, Enter/Space 키로 활성 상태를 토글한다.
Signature
function useClickToggle(options?: ClickToggleOptions): ClickToggleReturn
interface ClickToggleReturn {
isActive: boolean
mounted: boolean
toggle: () => void
activate: () => void
deactivate: () => void
reset: () => void
clickHandlers: {
onClick?: (event: React.MouseEvent) => void
onDoubleClick?: (event: React.MouseEvent) => void
onContextMenu?: (event: React.MouseEvent) => void
onKeyDown?: (event: React.KeyboardEvent) => void
}
}Parameters
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
initialState | boolean | false | 초기 상태 |
toggleOnClick | boolean | true | 클릭 시 토글 |
toggleOnDoubleClick | boolean | false | 더블클릭 시 토글 |
toggleOnRightClick | boolean | false | 우클릭 시 토글 |
toggleOnEnter | boolean | true | Enter 키로 토글 |
toggleOnSpace | boolean | true | Space 키로 토글 |
autoReset | boolean | false | 자동 리셋 여부 |
resetDelay | number | 3000 | 자동 리셋 지연 (ms) |
preventDefault | boolean | false | 기본 이벤트 방지 |
stopPropagation | boolean | false | 이벤트 전파 중단 |
Usage
import { useClickToggle } from '@hua-labs/motion-core'
function ToggleButton() {
const { isActive, clickHandlers, mounted } = useClickToggle({
toggleOnClick: true,
autoReset: true,
resetDelay: 2000
})
if (!mounted) return null
return (
<button
{...clickHandlers}
style={{ opacity: isActive ? 1 : 0.6 }}
>
{isActive ? '활성' : '비활성'}
</button>
)
}useFocusToggle
포커스/블러 이벤트로 활성 상태를 토글한다.
Signature
function useFocusToggle(options?: FocusToggleOptions): FocusToggleReturn
interface FocusToggleReturn {
isActive: boolean
mounted: boolean
toggle: () => void
activate: () => void
deactivate: () => void
reset: () => void
focusHandlers: {
onFocus?: (event: React.FocusEvent) => void
onBlur?: (event: React.FocusEvent) => void
onFocusIn?: (event: React.FocusEvent) => void
onFocusOut?: (event: React.FocusEvent) => void
}
ref: RefObject<HTMLElement | null>
}Parameters
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
initialState | boolean | false | 초기 상태 |
toggleOnFocus | boolean | true | 포커스 시 활성화 |
toggleOnBlur | boolean | false | 블러 시 비활성화 |
autoReset | boolean | false | 자동 리셋 |
resetDelay | number | 3000 | 자동 리셋 지연 (ms) |
Usage
import { useFocusToggle } from '@hua-labs/motion-core'
function FocusInput() {
const { isActive, focusHandlers } = useFocusToggle({
toggleOnFocus: true,
toggleOnBlur: true
})
return (
<input
{...focusHandlers}
style={{
outline: isActive ? '2px solid blue' : 'none',
transition: 'outline 150ms ease'
}}
/>
)
}useButtonEffect
버튼에 scale, ripple, glow, shake, bounce, slide 등 다양한 시각 효과를 적용한다.
Signature
function useButtonEffect<T extends MotionElement = HTMLButtonElement>(
options?: ButtonEffectOptions
): BaseMotionReturn<T> & {
buttonType: string
isPressed: boolean
isHovered: boolean
isFocused: boolean
ripplePosition: { x: number; y: number }
currentGlowIntensity: number
shakeOffset: number
bounceOffset: number
slideOffset: number
pressButton: () => void
releaseButton: () => void
setButtonState: (state: 'idle' | 'hover' | 'active' | 'focus' | 'disabled') => void
}Parameters (주요)
| 파라미터 | 타입 | 기본값 | 설명 | |||||
|---|---|---|---|---|---|---|---|---|
type | `'scale' \ | 'ripple' \ | 'glow' \ | 'shake' \ | 'bounce' \ | 'slide'` | 'scale' | 효과 타입 |
hoverScale | number | 1.05 | 호버 스케일 | |||||
activeScale | number | 0.95 | 클릭 스케일 | |||||
duration | number | 200 | 전환 시간 (ms) | |||||
disabled | boolean | false | 비활성화 | |||||
disabledOpacity | number | 0.5 | 비활성화 시 투명도 |
Usage
import { useButtonEffect } from '@hua-labs/motion-core'
function AnimatedButton() {
const { ref, style, pressButton, releaseButton } = useButtonEffect({
type: 'scale',
hoverScale: 1.08,
activeScale: 0.92
})
return (
<button
ref={ref}
style={style}
onMouseDown={pressButton}
onMouseUp={releaseButton}
>
클릭해 보세요
</button>
)
}useInteractive
호버/클릭 상태에 따른 스케일 변화를 간단하게 관리하는 내부 유틸리티 훅이다.
Signature
function useInteractive(config?: InteractiveConfig): {
ref: (element: HTMLDivElement | null) => void
scale: number
isHovered: boolean
isClicked: boolean
handleMouseEnter: () => void
handleMouseLeave: () => void
handleMouseDown: () => void
handleMouseUp: () => void
}
interface InteractiveConfig {
hoverScale?: number // 기본값: 1.05
clickScale?: number // 기본값: 0.95
duration?: number // 기본값: 200
}Usage
import { useInteractive } from '@hua-labs/motion-core'
function InteractiveCard() {
const {
ref,
scale,
handleMouseEnter,
handleMouseLeave,
handleMouseDown,
handleMouseUp
} = useInteractive({ hoverScale: 1.03, clickScale: 0.98 })
return (
<div
ref={ref}
style={{ transform: `scale(${scale})`, transition: 'transform 200ms ease' }}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
>
카드
</div>
)
}useKeyboardToggle
키보드 입력으로 활성 상태를 토글한다. 키 조합(key combo)과 전역 리스너를 지원한다.
Signature
function useKeyboardToggle(options?: KeyboardToggleConfig): KeyboardToggleReturn
interface KeyboardToggleReturn {
isActive: boolean
mounted: boolean
toggle: () => void
activate: () => void
deactivate: () => void
reset: () => void
keyboardHandlers: {
onKeyDown?: (event: React.KeyboardEvent) => void
onKeyUp?: (event: React.KeyboardEvent) => void
onKeyPress?: (event: React.KeyboardEvent) => void
}
ref: RefObject<HTMLElement | null>
}Parameters
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
keys | string[] | [' '] | 토글할 키 목록 |
keyCombo | string[] | — | 키 조합 (예: ['Control', 'K']) |
toggleOnKeyDown | boolean | true | 키다운 시 토글 |
toggleOnKeyUp | boolean | false | 키업 시 토글 |
requireFocus | boolean | false | 포커스된 요소에서만 동작 |
autoReset | boolean | false | 자동 리셋 |
resetDelay | number | 3000 | 자동 리셋 지연 (ms) |
Usage
import { useKeyboardToggle } from '@hua-labs/motion-core'
function SearchModal() {
// Ctrl+K로 토글
const { isActive } = useKeyboardToggle({
keyCombo: ['Control', 'k'],
preventDefault: true
})
return isActive ? <div>검색 모달</div> : null
}Notes
useClickToggle,useFocusToggle,useKeyboardToggle은 모두mounted상태를 반환하므로 SSR 하이드레이션 이슈에 주의한다.useButtonEffect의ripple타입은createRipple함수를 마우스 이벤트에 직접 연결해야 한다.useInteractive는@internal태그가 붙어 있으며 패키지 내부 용도로 설계됐다.