From c37ed3d4187081c04606b53a9569d22d5dd63793 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Wed, 2 Dec 2020 11:36:24 -0300 Subject: [PATCH 1/5] I18n Better Experience --- .../common/I18nWidget/I18nWidget.module.css | 14 +++++++ components/common/I18nWidget/I18nWidget.tsx | 38 ++++++++----------- components/icons/ChevronUp.tsx | 20 ++++++++++ components/icons/index.ts | 1 + 4 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 components/icons/ChevronUp.tsx diff --git a/components/common/I18nWidget/I18nWidget.module.css b/components/common/I18nWidget/I18nWidget.module.css index 6e8883521..07a1aeba7 100644 --- a/components/common/I18nWidget/I18nWidget.module.css +++ b/components/common/I18nWidget/I18nWidget.module.css @@ -6,6 +6,10 @@ @apply h-10 px-2 rounded-md border border-accents-2 flex items-center justify-center; } +.button:hover { + @apply border-accents-4 shadow-sm; +} + .button:focus { @apply outline-none; } @@ -18,6 +22,12 @@ } } +.closeButton { + @screen md { + @apply hidden; + } +} + .item { @apply flex cursor-pointer px-6 py-3 flex transition ease-in-out duration-150 text-primary leading-6 font-medium items-center; text-transform: capitalize; @@ -26,3 +36,7 @@ .item:hover { @apply bg-accents-1; } + +.icon { + transform: rotate(180deg); +} diff --git a/components/common/I18nWidget/I18nWidget.tsx b/components/common/I18nWidget/I18nWidget.tsx index d533e8c5e..5c82e3a9a 100644 --- a/components/common/I18nWidget/I18nWidget.tsx +++ b/components/common/I18nWidget/I18nWidget.tsx @@ -3,7 +3,7 @@ import Link from 'next/link' import { FC, useState } from 'react' import { useRouter } from 'next/router' import s from './I18nWidget.module.css' -import { Cross } from '@components/icons' +import { Cross, ChevronUp } from '@components/icons' interface LOCALE_DATA { name: string img: { @@ -43,29 +43,21 @@ const I18nWidget: FC = () => { return ( + ) } diff --git a/lib/click-outside/click-outside.tsx b/lib/click-outside/click-outside.tsx new file mode 100644 index 000000000..2af0497a6 --- /dev/null +++ b/lib/click-outside/click-outside.tsx @@ -0,0 +1,45 @@ +import React, { forwardRef, useEffect, Ref, MouseEvent } from 'react' +import hasParent from './has-parent' + +interface ClickOutsideProps { + active: boolean + onClick: (e?: MouseEvent) => void + children: any +} + +const ClickOutside = ( + { active = true, onClick, children }: ClickOutsideProps, + ref: Ref | null | any = {} +) => { + console.log('--------', active, '-----------') + const innerRef = ref?.current + + const handleClick = (event: any) => { + console.log(innerRef, event.target) + if (!hasParent(event.target, innerRef)) { + if (typeof onClick === 'function') { + event.preventDefault() + event.stopImmediatePropagation() + onClick(event) + } + } + } + + useEffect(() => { + if (active) { + document.addEventListener('mousedown', handleClick) + document.addEventListener('touchstart', handleClick) + } + + return () => { + if (active) { + document.removeEventListener('mousedown', handleClick) + document.removeEventListener('touchstart', handleClick) + } + } + }) + + return React.cloneElement(children, { ref }) +} + +export default forwardRef(ClickOutside) diff --git a/lib/click-outside/has-parent.js b/lib/click-outside/has-parent.js new file mode 100644 index 000000000..06cd3ca91 --- /dev/null +++ b/lib/click-outside/has-parent.js @@ -0,0 +1,5 @@ +import isInDOM from './is-in-dom' + +export default function hasParent(element, root) { + return root && root.contains(element) && isInDOM(element) +} diff --git a/lib/click-outside/index.ts b/lib/click-outside/index.ts new file mode 100644 index 000000000..2df916f9c --- /dev/null +++ b/lib/click-outside/index.ts @@ -0,0 +1 @@ +export { default } from './click-outside' diff --git a/lib/click-outside/is-in-dom.js b/lib/click-outside/is-in-dom.js new file mode 100644 index 000000000..5d7438ed7 --- /dev/null +++ b/lib/click-outside/is-in-dom.js @@ -0,0 +1,3 @@ +export default function isInDom(obj) { + return Boolean(obj.closest('body')) +} From 3f5045d3a8c5a08acd18d683c9862aa3651422a7 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Wed, 2 Dec 2020 13:17:30 -0300 Subject: [PATCH 3/5] Adding Click Outside --- lib/click-outside/click-outside.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/click-outside/click-outside.tsx b/lib/click-outside/click-outside.tsx index 2af0497a6..0cb491aef 100644 --- a/lib/click-outside/click-outside.tsx +++ b/lib/click-outside/click-outside.tsx @@ -11,11 +11,9 @@ const ClickOutside = ( { active = true, onClick, children }: ClickOutsideProps, ref: Ref | null | any = {} ) => { - console.log('--------', active, '-----------') const innerRef = ref?.current const handleClick = (event: any) => { - console.log(innerRef, event.target) if (!hasParent(event.target, innerRef)) { if (typeof onClick === 'function') { event.preventDefault() From 95897aa1c5efc3561b3a8ec1e0877f548006e890 Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Wed, 2 Dec 2020 13:22:41 -0300 Subject: [PATCH 4/5] Disable & Block Scroll and Click Outside for Dropdown Menu --- components/common/UserNav/DropdownMenu.tsx | 135 ++++++++++++--------- 1 file changed, 78 insertions(+), 57 deletions(-) diff --git a/components/common/UserNav/DropdownMenu.tsx b/components/common/UserNav/DropdownMenu.tsx index 99b92dff0..fb3ddc7de 100644 --- a/components/common/UserNav/DropdownMenu.tsx +++ b/components/common/UserNav/DropdownMenu.tsx @@ -1,12 +1,18 @@ import cn from 'classnames' import Link from 'next/link' -import { FC, useState } from 'react' +import { FC, useRef, useState, useEffect } from 'react' import { useTheme } from 'next-themes' import { useRouter } from 'next/router' import s from './DropdownMenu.module.css' import { Avatar } from '@components/common' import { Moon, Sun } from '@components/icons' import { useUI } from '@components/ui/context' +import ClickOutside from '@lib/click-outside' +import { + disableBodyScroll, + enableBodyScroll, + clearAllBodyScrollLocks, +} from 'body-scroll-lock' import useLogout from '@bigcommerce/storefront-data-hooks/use-logout' interface DropdownMenuProps { @@ -34,65 +40,80 @@ const DropdownMenu: FC = ({ open = false }) => { const { theme, setTheme } = useTheme() const [display, setDisplay] = useState(false) const { closeSidebarIfPresent } = useUI() + const ref = useRef() as React.MutableRefObject + + useEffect(() => { + if (ref.current) { + if (display) { + disableBodyScroll(ref.current) + } else { + enableBodyScroll(ref.current) + } + } + return () => { + clearAllBodyScrollLocks() + } + }, [display]) return ( -
- - - {display && ( - + )} +
+ ) } From 3770ad7ea822fc8c5ea11018cf1c318ba19de0fc Mon Sep 17 00:00:00 2001 From: Belen Curcio Date: Wed, 2 Dec 2020 13:24:25 -0300 Subject: [PATCH 5/5] forwardRef --- lib/click-outside/click-outside.tsx | 54 +++++++++++++++-------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/lib/click-outside/click-outside.tsx b/lib/click-outside/click-outside.tsx index 0cb491aef..d3bba953c 100644 --- a/lib/click-outside/click-outside.tsx +++ b/lib/click-outside/click-outside.tsx @@ -7,37 +7,39 @@ interface ClickOutsideProps { children: any } -const ClickOutside = ( - { active = true, onClick, children }: ClickOutsideProps, - ref: Ref | null | any = {} -) => { - const innerRef = ref?.current +const ClickOutside = forwardRef( + ( + { active = true, onClick, children }: ClickOutsideProps, + ref: Ref | null | any = {} + ) => { + const innerRef = ref?.current - const handleClick = (event: any) => { - if (!hasParent(event.target, innerRef)) { - if (typeof onClick === 'function') { - event.preventDefault() - event.stopImmediatePropagation() - onClick(event) + const handleClick = (event: any) => { + if (!hasParent(event.target, innerRef)) { + if (typeof onClick === 'function') { + event.preventDefault() + event.stopImmediatePropagation() + onClick(event) + } } } - } - useEffect(() => { - if (active) { - document.addEventListener('mousedown', handleClick) - document.addEventListener('touchstart', handleClick) - } - - return () => { + useEffect(() => { if (active) { - document.removeEventListener('mousedown', handleClick) - document.removeEventListener('touchstart', handleClick) + document.addEventListener('mousedown', handleClick) + document.addEventListener('touchstart', handleClick) } - } - }) - return React.cloneElement(children, { ref }) -} + return () => { + if (active) { + document.removeEventListener('mousedown', handleClick) + document.removeEventListener('touchstart', handleClick) + } + } + }) -export default forwardRef(ClickOutside) + return React.cloneElement(children, { ref }) + } +) + +export default ClickOutside