@mks2508/mks-ui
Primitives

Morph

Shape morphing primitive supporting multiple techniques - FLIP+clip-path, CSS Grid, and View Transitions API.

Morph

A morphing animation primitive that supports multiple techniques for smooth shape transitions between elements.

Import

import {
  Morph,
  useMorph,
  useMorphContext,
  useFLIPClipPath,
  useCSSGridMorph,
  useViewTransitions,
} from '@mks2508/mks-ui/react';

Techniques

TechniqueDescriptionBrowser Support
flip-clip-pathFLIP positioning + clip-path revealAll browsers
css-gridCSS Grid 0fr/1fr expand/collapseModern browsers
view-transitionsNative View Transitions APIChrome 111+, Edge 111+

Basic Usage

import { Morph, useMorphContext } from '@mks2508/mks-ui/react';

function MorphExample() {
  return (
    <Morph
      technique="flip-clip-path"
      duration={300}
      onMorphStart={() => console.log('Starting...')}
      onMorphEnd={() => console.log('Done!')}
    >
      {/* Children can use useMorphContext() */}
    </Morph>
  );
}

useMorph Hook

For imperative control over morphing:

import { useMorph } from '@mks2508/mks-ui/react';

function CustomMorph() {
  const fromRef = useRef<HTMLDivElement>(null);
  const toRef = useRef<HTMLDivElement>(null);

  const { morph, isMorphing } = useMorph({
    technique: 'flip-clip-path',
    duration: 300,
    easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
  });

  const handleMorph = async () => {
    if (!isMorphing()) {
      await morph(fromRef.current, toRef.current);
    }
  };

  return (
    <>
      <div ref={fromRef} onClick={handleMorph}>From</div>
      <div ref={toRef}>To</div>
    </>
  );
}

Technique Hooks

useFLIPClipPath

FLIP positioning combined with clip-path reveal:

import { useFLIPClipPath } from '@mks2508/mks-ui/react';

const flipClip = useFLIPClipPath({
  duration: 300,
  easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
});

// Morph from one element to another
await flipClip.morph(fromElement, toElement, {
  clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0 100%)', // optional custom clip-path
});

Features:

  • Calculates position and scale deltas
  • Applies inverse transform on target
  • Animates clip-path from point to full rect
  • Cross-fade opacity between states

useCSSGridMorph

CSS Grid-based expand/collapse using 0fr/1fr:

import { useCSSGridMorph } from '@mks2508/mks-ui/react';

const gridMorph = useCSSGridMorph({
  duration: 300,
  easing: 'ease',
});

// Expand container
await gridMorph.expand(containerRef);

// Collapse container
await gridMorph.collapse(containerRef);

// Toggle state
await gridMorph.toggle(containerRef);

Works by animating grid-template-rows between 0fr and 1fr.

useViewTransitions

View Transitions API wrapper with feature detection:

import { useViewTransitions } from '@mks2508/mks-ui/react';

const viewTrans = useViewTransitions();

// Check browser support
if (viewTrans.isSupported()) {
  await viewTrans.startTransition(async () => {
    // Make DOM changes here
    // The browser will automatically morph between states
  });
}

Features:

  • Automatic feature detection
  • startTransition() wraps document.startViewTransition
  • Custom view-transition-name generation
  • Cleanup on finish/error

API Reference

Morph Props

PropTypeDefaultDescription
technique'flip-clip-path' | 'css-grid' | 'view-transitions''flip-clip-path'Morphing technique
durationnumber300Animation duration (ms)
easingstring'cubic-bezier(0.4, 0, 0.2, 1)'CSS easing
classNamestringContainer class
onMorphStart() => voidStart callback
onMorphEnd() => voidEnd callback
childrenReactNodeChild elements

useMorph Config

OptionTypeDefaultDescription
techniqueMorphTechnique'flip-clip-path'Technique to use
durationnumber300Duration (ms)
easingstringCSS easing
onMorphStart() => voidStart callback
onMorphEnd() => voidEnd callback

useMorph Return

PropertyTypeDescription
morph(from, to) => Promise<void>Execute morph animation
isMorphing() => booleanCheck if animating

useFLIPClipPath Options

OptionTypeDefaultDescription
durationnumber300Duration (ms)
easingstringCSS easing

useCSSGridMorph Options

OptionTypeDefaultDescription
durationnumber300Duration (ms)
easingstring'ease'CSS easing

useViewTransitions Return

PropertyTypeDescription
isSupported() => booleanCheck browser support
startTransition(callback) => Promise<void>Start transition