Skip to content

Commit

Permalink
ToggleGroupControl: rewrite backdrop animation with framer motion sha…
Browse files Browse the repository at this point in the history
…red layout animations (#50278)

* Reuse previous implementation

* Reset motion context in slot-fill

* Memoize classes

* Move layout group to root component

* Use useLayoutEffect to apply internal state changes

* CHANGELOG

* Update snapshots

* Expose motion context from the components package

* Refactor inspector controls slot/fill to accept an array of context provider/values under fillprops.forwardedContext

* Add framer motion context to the forwarded contexts in inspector controls slot/fill

* Remove hardcoded motion provider from fill component, update slot fill storybook example

* CHANGELOG update

* Update as button group to also use useLayoutEffect

* Use controlled version of the component in unit tests

* Improve context provider storybook types

* Fix register/deregister logic for toolspanel in inspector controls

* extract useUpdateLayoutEffect to separate util hook

* Better fillprops forwarded context type

* Change docs to have controlled usage

* Reuse types

* Add defaultValue prop

* Refactor component to handle both controlled and uncontrolled updates

* Remove unused `useUpdateLayoutEffect` hook

* Update unit tess: check both controlled and uncontrolled, use initialvalue

* Introduce logic to distinguish undefined as controlled or uncontrolled update

* Bring back README example to be uncontrolled, but use `defaultValue`

* Update `defaultValue` prop description, add to README

* Stop using deprecated `ReactText` type, use `string | number` instead

* Add keyboard interaction with reset unit test

* Add reset button to Storybook example

* Refactor to ariakit

* Pass props to `button` instead of `radio`

* add support for uncontrolled without the `defaultValue` prop

* Update snappshots

* Restore README

* Update CHANGELOG

* Format

* Fix format (again)

* Remove unnecessary cast to string when using `useInstanceId`

* Remove temporary Storybook changes

* CHANGELOG
  • Loading branch information
ciampo authored Sep 5, 2023
1 parent ed1a95b commit 10859af
Show file tree
Hide file tree
Showing 18 changed files with 1,002 additions and 390 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@
* WordPress dependencies
*/
import { __experimentalToolsPanelContext as ToolsPanelContext } from '@wordpress/components';
import { useContext } from '@wordpress/element';
import { useContext, useMemo } from '@wordpress/element';

export default function BlockSupportSlotContainer( { Slot, ...props } ) {
export default function BlockSupportSlotContainer( {
Slot,
fillProps,
...props
} ) {
// Add the toolspanel context provider and value to existing fill props
const toolsPanelContext = useContext( ToolsPanelContext );
const computedFillProps = useMemo(
() => ( {
...( fillProps ?? {} ),
forwardedContext: [
...( fillProps?.forwardedContext ?? [] ),
[ ToolsPanelContext.Provider, { value: toolsPanelContext } ],
],
} ),
[ toolsPanelContext, fillProps ]
);

return (
<Slot { ...props } fillProps={ toolsPanelContext } bubblesVirtually />
<Slot { ...props } fillProps={ computedFillProps } bubblesVirtually />
);
}
42 changes: 28 additions & 14 deletions packages/block-editor/src/components/inspector-controls/fill.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@wordpress/components';
import warning from '@wordpress/warning';
import deprecated from '@wordpress/deprecated';
import { useEffect } from '@wordpress/element';
import { useEffect, useContext } from '@wordpress/element';

/**
* Internal dependencies
Expand Down Expand Up @@ -60,28 +60,42 @@ export default function InspectorControlsFill( {
);
}

function ToolsPanelInspectorControl( { children, resetAllFilter, fillProps } ) {
const { registerResetAllFilter, deregisterResetAllFilter } = fillProps;
function RegisterResetAll( { resetAllFilter, children } ) {
const { registerResetAllFilter, deregisterResetAllFilter } =
useContext( ToolsPanelContext );
useEffect( () => {
if ( resetAllFilter && registerResetAllFilter ) {
if (
resetAllFilter &&
registerResetAllFilter &&
deregisterResetAllFilter
) {
registerResetAllFilter( resetAllFilter );
}
return () => {
if ( resetAllFilter && deregisterResetAllFilter ) {
return () => {
deregisterResetAllFilter( resetAllFilter );
}
};
};
}
}, [ resetAllFilter, registerResetAllFilter, deregisterResetAllFilter ] );
return children;
}

function ToolsPanelInspectorControl( { children, resetAllFilter, fillProps } ) {
// `fillProps.forwardedContext` is an array of context provider entries, provided by slot,
// that should wrap the fill markup.
const { forwardedContext = [] } = fillProps;

// Children passed to InspectorControlsFill will not have
// access to any React Context whose Provider is part of
// the InspectorControlsSlot tree. So we re-create the
// Provider in this subtree.
const value =
fillProps && Object.keys( fillProps ).length > 0 ? fillProps : null;
return (
<ToolsPanelContext.Provider value={ value }>
const innerMarkup = (
<RegisterResetAll resetAllFilter={ resetAllFilter }>
{ children }
</ToolsPanelContext.Provider>
</RegisterResetAll>
);
return forwardedContext.reduce(
( inner, [ Provider, props ] ) => (
<Provider { ...props }>{ inner }</Provider>
),
innerMarkup
);
}
31 changes: 28 additions & 3 deletions packages/block-editor/src/components/inspector-controls/slot.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* WordPress dependencies
*/
import { __experimentalUseSlotFills as useSlotFills } from '@wordpress/components';
import {
__experimentalUseSlotFills as useSlotFills,
__unstableMotionContext as MotionContext,
} from '@wordpress/components';
import { useContext, useMemo } from '@wordpress/element';
import warning from '@wordpress/warning';
import deprecated from '@wordpress/deprecated';

Expand All @@ -16,6 +20,7 @@ export default function InspectorControlsSlot( {
__experimentalGroup,
group = 'default',
label,
fillProps,
...props
} ) {
if ( __experimentalGroup ) {
Expand All @@ -31,6 +36,20 @@ export default function InspectorControlsSlot( {
}
const Slot = groups[ group ]?.Slot;
const fills = useSlotFills( Slot?.__unstableName );

const motionContextValue = useContext( MotionContext );

const computedFillProps = useMemo(
() => ( {
...( fillProps ?? {} ),
forwardedContext: [
...( fillProps?.forwardedContext ?? [] ),
[ MotionContext.Provider, { value: motionContextValue } ],
],
} ),
[ motionContextValue, fillProps ]
);

if ( ! Slot ) {
warning( `Unknown InspectorControls group "${ group }" provided.` );
return null;
Expand All @@ -43,10 +62,16 @@ export default function InspectorControlsSlot( {
if ( label ) {
return (
<BlockSupportToolsPanel group={ group } label={ label }>
<BlockSupportSlotContainer { ...props } Slot={ Slot } />
<BlockSupportSlotContainer
{ ...props }
fillProps={ computedFillProps }
Slot={ Slot }
/>
</BlockSupportToolsPanel>
);
}

return <Slot { ...props } bubblesVirtually />;
return (
<Slot { ...props } fillProps={ computedFillProps } bubblesVirtually />
);
}
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Enhancements

- Making Circular Option Picker a `listbox`. Note that while this changes some public API, new props are optional, and currently have default values; this will change in another patch ([#52255](https://github.com/WordPress/gutenberg/pull/52255)).
- `ToggleGroupControl`: Rewrite backdrop animation using framer motion shared layout animations, add better support for controlled and uncontrolled modes ([#50278](https://github.com/WordPress/gutenberg/pull/50278)).
- `Popover`: Add the `is-positioned` CSS class only after the popover has finished animating ([#54178](https://github.com/WordPress/gutenberg/pull/54178)).

### Bug Fix
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/animation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
export {
motion as __unstableMotion,
AnimatePresence as __unstableAnimatePresence,
MotionContext as __unstableMotionContext,
} from 'framer-motion';
6 changes: 5 additions & 1 deletion packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export {
default as Animate,
getAnimateClassName as __unstableGetAnimateClassName,
} from './animate';
export { __unstableMotion, __unstableAnimatePresence } from './animation';
export {
__unstableMotion,
__unstableAnimatePresence,
__unstableMotionContext,
} from './animation';
export { default as AnglePickerControl } from './angle-picker-control';
export {
default as Autocomplete,
Expand Down
Loading

0 comments on commit 10859af

Please sign in to comment.