Skip to content

Commit

Permalink
fix(Picker): add open/close transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
LexSwed committed Nov 3, 2020
1 parent 8d5ce34 commit 0579f7d
Show file tree
Hide file tree
Showing 6 changed files with 497 additions and 416 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@
},
"devDependencies": {
"@chakra-ui/core": "^0.8.0",
"@emotion/core": "^10.1.0",
"@emotion/core": "^10.1.1",
"@emotion/styled": "^10.0.27",
"@types/jest": "^26.0.15",
"@types/node": "^14.14.6",
"@types/react": "^16.9.55",
"@typescript-eslint/eslint-plugin": "^4.6.0",
"@typescript-eslint/parser": "^4.6.0",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.6.1",
"babel-eslint": "^10.1.0",
"babel-preset-react-app": "^10.0.0",
"dokz": "^1.0.79",
Expand All @@ -62,7 +62,7 @@
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.0",
"jest": "^26.6.1",
"jest": "^26.6.2",
"microbundle": "^0.12.4",
"next": "^10.0.0",
"npm-run-all": "^4.1.5",
Expand Down
35 changes: 25 additions & 10 deletions src/lib/Popover/Popover.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Options } from '@popperjs/core';
import { AnimatePresence, motion } from 'framer-motion';
import React, { useMemo } from 'react';
import Portal from '../Portal';
import { styled } from '../stitches.config';
Expand All @@ -8,6 +9,9 @@ import { useOpenState, useOpenStateControls } from '../utils/OpenStateProvider';
const Popper = styled('div', {
zIndex: '$2',
position: 'absolute',
});

const PopperBox = styled(motion.div, {
bc: '$surfaceStill',
br: '$md',
border: '1px solid $borderLight',
Expand Down Expand Up @@ -36,7 +40,7 @@ const Popover: React.FC<Props> = ({ children, triggerRef, offset = 8, placement
)
);

useOnClickOutside(close, popperRef, triggerRef);
useOnClickOutside(close, isOpen, popperRef, triggerRef);

const handleKeyDown = useKeyboardHandles(
useMemo(
Expand All @@ -48,16 +52,27 @@ const Popover: React.FC<Props> = ({ children, triggerRef, offset = 8, placement
)
);

if (!isOpen) {
return null;
}

return (
<Portal>
<Popper ref={popperRef as any} onKeyDown={handleKeyDown}>
{children}
</Popper>
</Portal>
<AnimatePresence>
{isOpen && (
<Portal>
<Popper ref={popperRef as any} onKeyDown={handleKeyDown}>
<PopperBox
initial={{ opacity: 0, y: -5 }}
animate={{
opacity: 1,
y: 0,
transition: { duration: 0.15, opacity: { duration: 0.1 } },
}}
exit={{ opacity: 0, y: -5 }}
transition={{ duration: 0.1, type: 'tween' }}
>
{children}
</PopperBox>
</Popper>
</Portal>
)}
</AnimatePresence>
);
};

Expand Down
8 changes: 5 additions & 3 deletions src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,17 @@ type Handler = (event: PossibleEvent) => void;

const events: HandledEventsType[] = [MOUSEDOWN, TOUCHSTART, POINTERDOWN];

export function useOnClickOutside(handler: Handler | null, ...refs: React.RefObject<HTMLElement>[]) {
export function useOnClickOutside(handler: Handler | null, isActive: boolean, ...refs: React.RefObject<HTMLElement>[]) {
const handlerRef = useLatest(handler);

useEffect(() => {
if (!isActive) {
return;
}
const listener = (event: PossibleEvent) => {
if (refs.some((ref) => ref.current?.contains?.(event.target as Node))) {
return;
}

handlerRef.current?.(event);
};

Expand All @@ -109,7 +111,7 @@ export function useOnClickOutside(handler: Handler | null, ...refs: React.RefObj
document.removeEventListener(event, listener);
});
};
}, [handlerRef, ...refs]); //eslint-disable-line react-hooks/exhaustive-deps
}, [handlerRef, isActive, ...refs]); //eslint-disable-line react-hooks/exhaustive-deps
}

export function usePopper(
Expand Down
56 changes: 56 additions & 0 deletions src/pages/components/Picker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,59 @@ Supports same `variant`s as `TextField` component.
);
}}
</Playground>

## Variants

Supports same `variant`s as `TextField` component.

<Playground>
{() => {
const [value, setValue] = React.useState('12');
return (
<Box css={{ p: '$8', bc: '$surfaceStill' }}>
<Flex space="md" css={{ width: '$40' }} cross="stretch">
<Picker
label="Item index"
variant="underlined"
placeholder="1 number"
validity={Number(value) > 10 ? 'valid' : 'invalid'}
>
{Array(20)
.fill(null)
.map((el, i) => (
<Picker.Item key={i} value={`${i + 1}`} label={`Item ${i + 1}`} />
))}
</Picker>
</Flex>
</Box>
);
}}
</Playground>

## Variants

Supports same `variant`s as `TextField` component.

<Playground>
{() => {
const [value, setValue] = React.useState('12');
return (
<Box css={{ p: '$8', bc: '$surfaceStill' }}>
<Flex space="md" css={{ width: '$40' }} cross="stretch">
<Picker
label="Item index"
variant="underlined"
placeholder="1 number"
validity={Number(value) > 10 ? 'valid' : 'invalid'}
>
{Array(20)
.fill(null)
.map((el, i) => (
<Picker.Item key={i} value={`${i + 1}`} label={`Item ${i + 1}`} />
))}
</Picker>
</Flex>
</Box>
);
}}
</Playground>
3 changes: 2 additions & 1 deletion tsconfig.lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"declaration": true
"declaration": true,
"strictFunctionTypes": true
},
"include": ["src/lib/**/*"],
"exclude": ["node_modules"]
Expand Down
Loading

1 comment on commit 0579f7d

@vercel
Copy link

@vercel vercel bot commented on 0579f7d Nov 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.