Skip to content

Commit

Permalink
feat: onAnimationEnd prop (#419)
Browse files Browse the repository at this point in the history
* Add onAnimationEnd prop

* cleanup

* Fix typescript error

* Cleanup

* Bring back disablePreventScroll
  • Loading branch information
emilkowalski authored Sep 15, 2024
1 parent 85b830f commit 1953787
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 10 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Additional props:

`snapToSequentialPoint`: Disabled velocity based swiping for snap points. This means that a snap point won't be skipped even if the velocity is high enough. Useful if each snap point in a drawer is equally important.

`onAnimationEnd`: Gets triggered after the open or close animation ends, it receives an `open` argument with the `open` state of the drawer by the time the function was triggered. Useful to revert any state changes for example.

`[data-vaul-no-drag]`: When interacting with an element with this data attribute, the drawer won't be dragged.

### Controlled Drawer
Expand Down
31 changes: 21 additions & 10 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ export type DialogProps = {
onClose?: () => void;
direction?: 'top' | 'bottom' | 'left' | 'right';
defaultOpen?: boolean;
disablePreventScroll?: boolean;
repositionInputs?: boolean;
snapToSequentialPoint?: boolean;
container?: HTMLElement | null;
onAnimationEnd?: (open: boolean) => void;
} & (WithFadeFromProps | WithoutFadeFromProps);

export function Root({
Expand All @@ -78,14 +80,22 @@ export function Root({
noBodyStyles,
direction = 'bottom',
defaultOpen = false,
disablePreventScroll = true,
snapToSequentialPoint = false,
repositionInputs = true,
onAnimationEnd,
container,
}: DialogProps) {
const [isOpen = false, setIsOpen] = useControllableState({
defaultProp: defaultOpen,
prop: openProp,
onChange: onOpenChange,
onChange: (o: boolean) => {
onOpenChange?.(o);

setTimeout(() => {
onAnimationEnd?.(o);
}, TRANSITIONS.DURATION * 1000);
},
});
const [hasBeenOpened, setHasBeenOpened] = React.useState<boolean>(false);
const [isDragging, setIsDragging] = React.useState<boolean>(false);
Expand Down Expand Up @@ -132,7 +142,8 @@ export function Root({
});

usePreventScroll({
isDisabled: !isOpen || isDragging || !modal || justReleased || !hasBeenOpened || !repositionInputs,
isDisabled:
!isOpen || isDragging || !modal || justReleased || !hasBeenOpened || !repositionInputs || !disablePreventScroll,
});

function getScale() {
Expand Down Expand Up @@ -392,11 +403,13 @@ export function Root({
return () => window.visualViewport?.removeEventListener('resize', onVisualViewportChange);
}, [activeSnapPointIndex, snapPoints, snapPointsOffset]);

function closeDrawer() {
function closeDrawer(fromWithin?: boolean) {
cancelDrag();
onClose?.();

setIsOpen(false);
if (!fromWithin) {
setIsOpen(false);
}

setTimeout(() => {
if (snapPoints) {
Expand Down Expand Up @@ -607,8 +620,9 @@ export function Root({
if (open) {
setHasBeenOpened(true);
} else {
closeDrawer();
closeDrawer(true);
}

setIsOpen(open);
}}
open={isOpen}
Expand Down Expand Up @@ -669,12 +683,10 @@ export const Overlay = React.forwardRef<HTMLDivElement, React.ComponentPropsWith

Overlay.displayName = 'Drawer.Overlay';

export type ContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
onAnimationEnd?: (open: boolean) => void;
};
export type ContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;

export const Content = React.forwardRef<HTMLDivElement, ContentProps>(function (
{ onPointerDownOutside, onAnimationEnd, style, ...rest },
{ onPointerDownOutside, style, ...rest },
ref,
) {
const {
Expand Down Expand Up @@ -824,7 +836,6 @@ export function NestedRoot({ onDrag, onOpenChange, ...rest }: DialogProps) {
if (o) {
onNestedOpenChange(o);
}
onOpenChange?.(o);
}}
onRelease={onNestedRelease}
{...rest}
Expand Down

0 comments on commit 1953787

Please sign in to comment.