UNPKG

popmotion-pose

Version:

A declarative animation library for HTML and SVG

247 lines (159 loc) 6.75 kB
--- title: Posed description: Create a posed component category: react --- > React Pose has been **deprecated** in favour of [Framer Motion](https://framer.com/motion). [Read the upgrade guide](https://www.framer.com/api/motion/migrate-from-pose/) # posed `posed` is used to create animated and interactive components that you can reuse throughout your React site. <TOC /> ## Import ```javascript import posed from 'react-pose' ``` ## Usage ### Create a posed component `posed` can be used to create posed components in two ways: - **Recommended:** Create HTML & SVG elements (eg `posed.div`) - **Advanced:** Convert existing components (eg `posed(Component)`) #### HTML & SVG elements `pose` isn't called directly, instead we pass [a pose config object](/pose/api/react-config) to `posed.div`, `posed.button` etc. Every HTML and SVG element is supported: ```javascript const DraggableCircle = posed.circle({ draggable: 'x', dragBounds: { left: 0, right: 100 } }) export default ({ radius }) => <DraggableCircle r={radius} /> ``` #### Existing components Existing components can be converted to posed components by calling `posed` directly: ```javascript const PosedComponent = posed(MyComponent)(poseProps) ``` For performance and layout calculations, React Pose requires a reference to the underlying DOM element. So, the component to be animated **must pass forward a ref using the `React.forwardRef` function**: ```javascript const MyComponent = forwardRef((props, ref) => ( <div ref={ref} {...props} /> )); const PosedComponent = posed(MyComponent)({ draggable: true }); export default () => <PosedComponent pose={isOpen ? 'open' : 'closed'} /> ``` Many CSS-in-JS libraries like Styled Components will automatically do this for you. For FLIP support in a `PoseGroup` component, it **optionally** needs to pass on the `style` prop: ```javascript const MyComponent = forwardRef(({ style }, ref) => ( <div ref={ref} style={style} /> )); ``` ### Set a pose Poses can be set via the `pose` property. This can either be a string, or an array of strings to reference multiple poses: ```javascript const Sidebar = posed.nav({ open: { x: '0%' }, closed: { x: '-100%' } }) export default ({ isOpen }) => <Sidebar pose={isOpen ? 'open' : 'closed'} /> ``` ### Children Using a posed component creates a new tree of posed components. Any children that are also posed components are automatically added to this tree. This means that orchestrating animations through React trees becomes trivial, as a pose only has to be set on a parent. Any children with that pose defined will also animate: ```javascript const Sidebar = posed.nav({ open: { x: '0%', staggerChildren: 100 }, closed: { x: '-100%' } }) const NavItem = posed.li({ open: { opacity: 1 }, closed: { opacity: 0 } }) export default ({ isOpen, navItems }) => ( <Sidebar pose={isOpen ? 'open' : 'closed'}> <ul> {navItems.map(({ url, name }) => ( <NavItem> <a href={url}>{name}</a> </NavItem> ))} </ul> </Sidebar> ) ``` <CodePen id="MVQepE" /> In tandem with the [`PoseGroup`](/pose/api/posegroup) component, this capability can be used to orchestrate sophisticated `enter` and `exit` animations. This behaviour can be overridden by passing `newTree` to a posed component, which will ignore any parent posed components and create a new tree. ### Styling Posed components are normal components, so they can be used with any CSS styling solution. For instance: #### Styled Components ```javascript const sidebarProps = { open: { x: '0%' }, closed: { x: '-100%' } } const Sidebar = styled(posed.nav(sidebarProps))` ``` #### className ```javascript () => <Sidebar pose="closed" className="my-class" /> ``` ## Props ### pose `pose?: string | string[]` The name or names of the current pose. ### initialPose `initialPose?: string | string[]` The name of one or more poses to set to before the component mounts. Once the component mounts, it will transition from this pose into `pose`. ### poseKey `poseKey?: string | number` If `poseKey` changes, it'll force the posed component to transition to the current `pose`, even if it hasn't changed. This won't be required for the majority of use-cases. But we might have something like a paginated where we pass the x offset to the component but the pose itself doesn't change: ```javascript const Slider = posed.div({ nextItem: { x: ({ target }) => target } }) ({ target }) => <Slider pose="nextItem" poseKey={target} target={target} /> ``` ### withParent `withParent?: boolean = true` If set to `false`, this component won't subscribe to its parent posed component and create root for any further child components. ### onPoseComplete `onPoseComplete?: Function` A callback that fires whenever a pose has finished transitioning. ### onValueChange `onValueChange?: { [key: string]: any }` `onValueChange` is a map of functions, each corresponding to a value being animated by the posed component and will fire when that value changes. ### onDragStart/onDragEnd `onDragStart/onDragEnd: (e: Event) => void` Callbacks that fire when dragging starts or ends. **Note:** These props are immutable and can't be changed after mounting. ### onPressStart/onPressEnd `onPressStart/onPressEnd: (e: Event) => void` Callbacks that fire when pressing starts or ends. **Note:** These props are immutable and can't be changed after mounting. ### ref `ref?: RefObject | (ref: Element) => void` An optional ref property. If a function, will call with the posed DOM element when it mounts, and `null` when it unmounts. Alternatively, it can be passed a ref object (created from `React.createRef`). ### values/parentValues `values?: { [key: string]: Value }` Normally, Pose generates [Popmotion `value`](/api/value) for each animating property. It then passes these down to any posed children so `passive` values can link to them. Novel hierarchies, where the posed tree and the React component tree diverge, can be achieved by creating your own values map, and passing that to a single posed component. This same map can then be passed to multiple other posed component's `parentValues` property in order to establish a parent-children relationship even between sibling components. <CodePen id="xWrbNm" /> ### ...props `...props: { [key: string]: any }` When a new pose is entered, any remaining props set on a component will be used to resolve that pose's dynamic props: ```javascript const Component = posed.div({ visible: { opacity: 1, y: 0 }, hidden: { opacity: 0, y: ({ i }) => i * 50 } }) // Later ({ isVisibile, i }) => ( <Component pose={isVisible ? 'visible' : 'hidden'} i={i} /> ) ```