From f69d6de3ea85ab067d67f49bdd153de63a828ab5 Mon Sep 17 00:00:00 2001 From: theojungle Date: Mon, 24 Jul 2023 18:27:01 +0200 Subject: [PATCH] feat: migrate DropdownMenu component --- docs/components/Header/ThemeSelector.js | 18 ++-- docs/pages/_app.js | 5 +- docs/pages/components/dropdown-menu.mdx | 58 ++++++------- packages/DropdownMenu/README.md | 2 +- packages/DropdownMenu/package.json | 4 +- packages/DropdownMenu/src/Arrow.styled.ts | 4 +- packages/DropdownMenu/src/Arrow.tsx | 24 ++---- packages/DropdownMenu/src/Item.styled.ts | 5 -- packages/DropdownMenu/src/Item.tsx | 23 +---- packages/DropdownMenu/src/Separator.tsx | 13 +-- packages/DropdownMenu/src/index.tsx | 97 +++++----------------- packages/DropdownMenu/src/styles.ts | 14 ++-- packages/DropdownMenu/tests/index.test.tsx | 8 +- packages/System/src/index.tsx | 6 -- yarn.lock | 37 +-------- 15 files changed, 94 insertions(+), 224 deletions(-) diff --git a/docs/components/Header/ThemeSelector.js b/docs/components/Header/ThemeSelector.js index 77cdbb3648..d762ef0150 100644 --- a/docs/components/Header/ThemeSelector.js +++ b/docs/components/Header/ThemeSelector.js @@ -1,5 +1,5 @@ import React from 'react' -import { DropdownMenu, useDropdownMenuState } from '@welcome-ui/dropdown-menu' +import { DropdownMenu, useDropdownMenu } from '@welcome-ui/dropdown-menu' import { Box } from '@welcome-ui/box' import { CrescentMoonIcon, StarIcon, StarOutlineIcon, SunIcon } from '@welcome-ui/icons' import { Button } from '@welcome-ui/button' @@ -9,12 +9,12 @@ import { useSetThemeContext, useThemeContext } from '../../context/theme' export const ThemeSelector = props => { const setTheme = useSetThemeContext() - const menuState = useDropdownMenuState({ gutter: 10 }) + const dropdownMenu = useDropdownMenu() const theme = useThemeContext() const handleSetTheme = theme => { setTheme(theme) - menuState.hide() + dropdownMenu.hide() } const options = [ @@ -26,17 +26,23 @@ export const ThemeSelector = props => { return ( <> - + - + {options?.map(({ icon: Icon, isBeta, label, value }) => ( handleSetTheme(value)} - state={menuState} > {label} diff --git a/docs/pages/_app.js b/docs/pages/_app.js index e78f7f9a2a..c5bdfcb8b8 100644 --- a/docs/pages/_app.js +++ b/docs/pages/_app.js @@ -1,6 +1,5 @@ /* eslint-disable react/display-name */ import React from 'react' -import { Provider } from 'reakit' import { ThemeProvider } from '../context/theme' import { App } from '../components/App' @@ -10,9 +9,7 @@ require('@welcome-ui/icons.font/fonts/welcome-icon-font-2.css') const NextApp = ({ Component, pageProps }) => { return ( - - - + ) } diff --git a/docs/pages/components/dropdown-menu.mdx b/docs/pages/components/dropdown-menu.mdx index 2e9eecd462..51e0ac5512 100644 --- a/docs/pages/components/dropdown-menu.mdx +++ b/docs/pages/components/dropdown-menu.mdx @@ -18,38 +18,36 @@ import { ## About -Menu from [Reakit](https://reakit.io/docs/menu/) with a really nice theme 👀 +Menu from [Ariakit menu](https://ariakit.org/components/menu) with a really nice theme 👀 ## Usage ```jsx function() { - const dropdownMenuState = useDropdownMenuState({ - gutter: 10 - }) + const dropdownMenu = useDropdownMenu() const handleClick = e => { console.log(`Clicked on ${e.target.innerText}`) - dropdownMenuState.hide() + dropdownMenu.hide() } return ( <> - + Dropdown Menu - - + + Twitter - + Facebook - + Instagram - - + + Github @@ -62,11 +60,11 @@ function() { ```jsx function() { - const dropdownMenuState = useDropdownMenuState({ gutter: 10, placement: 'bottom-end' }) + const dropdownMenu = useDropdownMenu({ placement: 'bottom-end' }) const handleClick = e => { console.log(`Clicked on ${e.target.innerText}`) - dropdownMenuState.hide() + dropdownMenu.hide() } return ( @@ -76,16 +74,16 @@ function() { First Action - - {dropdownMenuState.open ? : } + + {dropdownMenu.open ? : } - - + + Second Action - + Third Action @@ -101,33 +99,31 @@ Use `DropdownMenu.Arrow` to add an arrow to the dropdown menu ```jsx function() { - const dropdownMenuState = useDropdownMenuState({ - gutter: 10 - }) + const dropdownMenu = useDropdownMenu() const handleClick = e => { console.log(`Clicked on ${e.target.innerText}`) - dropdownMenuState.hide() + dropdownMenu.hide() } return ( <> - + Dropdown Menu - - - + + + Twitter - + Facebook - + Instagram - - + + Github diff --git a/packages/DropdownMenu/README.md b/packages/DropdownMenu/README.md index 96d89bc525..e7d77caac7 100644 --- a/packages/DropdownMenu/README.md +++ b/packages/DropdownMenu/README.md @@ -10,7 +10,7 @@ The [DropdownMenu](https://welcome-ui.com/components/dropdown-menu) component fr ## Import - import { DropdownMenu, useDropdownMenuState } from '@welcome-ui/dropdown-menu' + import { DropdownMenu, useDropdownMenu } from '@welcome-ui/dropdown-menu' ## Documentation diff --git a/packages/DropdownMenu/package.json b/packages/DropdownMenu/package.json index c32609bb9b..fdeaaec39b 100644 --- a/packages/DropdownMenu/package.json +++ b/packages/DropdownMenu/package.json @@ -46,10 +46,10 @@ "url": "https://github.com/WTTJ/welcome-ui/issues" }, "dependencies": { + "@ariakit/react": "^0.2.12", "@welcome-ui/box": "^5.0.0-alpha.40", "@welcome-ui/system": "^5.0.0-alpha.40", - "@welcome-ui/utils": "^5.0.0-alpha.37", - "reakit": "^1.3.11" + "@welcome-ui/utils": "^5.0.0-alpha.37" }, "peerDependencies": { "@xstyled/styled-components": "^3.7.3", diff --git a/packages/DropdownMenu/src/Arrow.styled.ts b/packages/DropdownMenu/src/Arrow.styled.ts index dad17fe5fe..54ffb03b5c 100644 --- a/packages/DropdownMenu/src/Arrow.styled.ts +++ b/packages/DropdownMenu/src/Arrow.styled.ts @@ -1,10 +1,10 @@ import styled, { css, th } from '@xstyled/styled-components' -import { MenuArrow } from 'reakit' -export const Arrow = styled(MenuArrow)` +export const Arrow = styled.divBox` display: flex; z-index: 2; color: ${th('defaultCards.backgroundColor')}; + stroke-width: 0 !important; #stroke { color: ${th('defaultCards.borderColor')}; diff --git a/packages/DropdownMenu/src/Arrow.tsx b/packages/DropdownMenu/src/Arrow.tsx index 4a2af0c70f..69c7debe3f 100644 --- a/packages/DropdownMenu/src/Arrow.tsx +++ b/packages/DropdownMenu/src/Arrow.tsx @@ -1,11 +1,9 @@ import React from 'react' -import { MenuArrowOptions } from 'reakit' +import * as Ariakit from '@ariakit/react' import { CreateWuiProps, forwardRef } from '@welcome-ui/system' import * as S from './Arrow.styled' -import { DropdownMenuOptions } from '.' - const transformMap: Record = { top: 'rotateZ(180deg)', right: 'rotateZ(-90deg)', @@ -13,22 +11,16 @@ const transformMap: Record = { left: 'rotateZ(90deg)', } -export type ArrowProps = CreateWuiProps< - 'div', - MenuArrowOptions & { state: DropdownMenuOptions['state'] } -> +export type ArrowProps = CreateWuiProps<'div', Ariakit.MenuArrowProps> -export const Arrow = forwardRef<'div', ArrowProps>(({ state, ...rest }, ref) => { - // get the correct transform style for arrow - const { placement } = state - // get the parent placement (top, bottom...) - const [parentPlacement] = placement.split('-') - const transform = transformMap[parentPlacement] +export const Arrow = forwardRef<'div', ArrowProps>(({ store }, ref) => { + const currentPlacement = store?.useState('currentPlacement') + const [placement] = currentPlacement.split('-') return ( - + }> (({ state, ...rest }, ref) => - + ) }) diff --git a/packages/DropdownMenu/src/Item.styled.ts b/packages/DropdownMenu/src/Item.styled.ts index 54902f93a1..c894443dc1 100644 --- a/packages/DropdownMenu/src/Item.styled.ts +++ b/packages/DropdownMenu/src/Item.styled.ts @@ -12,11 +12,6 @@ export const Item = styled.button` text-decoration: none; padding: md; - &[type='button'] { - appearance: none; - } - - &:hover, &:focus { outline: none !important; /* important for firefox */ } diff --git a/packages/DropdownMenu/src/Item.tsx b/packages/DropdownMenu/src/Item.tsx index 28a877be12..51ea7d9e8e 100644 --- a/packages/DropdownMenu/src/Item.tsx +++ b/packages/DropdownMenu/src/Item.tsx @@ -1,28 +1,13 @@ import React from 'react' -import { MenuItem, MenuItemProps } from 'reakit' +import * as Ariakit from '@ariakit/react' import { CreateWuiProps, forwardRef } from '@welcome-ui/system' import * as S from './Item.styled' -import { DropdownMenuOptions } from '.' +export type ItemProps = CreateWuiProps<'button', Ariakit.MenuItemProps> -type ItemOptions = Pick & - Partial> - -export type ItemProps = CreateWuiProps<'button', ItemOptions> - -export const Item = forwardRef<'button', ItemProps>(({ as, children, state, ...rest }, ref) => { - return ( - - {menuItemProps => { - return ( - - {children} - - ) - }} - - ) +export const Item = forwardRef<'button', ItemProps>(({ as, ...rest }, ref) => { + return } /> }) Item.displayName = 'Item' diff --git a/packages/DropdownMenu/src/Separator.tsx b/packages/DropdownMenu/src/Separator.tsx index 3dded533d7..f991438b23 100644 --- a/packages/DropdownMenu/src/Separator.tsx +++ b/packages/DropdownMenu/src/Separator.tsx @@ -1,16 +1,11 @@ import React from 'react' -import { MenuSeparator, MenuSeparatorProps } from 'reakit' +import * as Ariakit from '@ariakit/react' import { CreateWuiProps, forwardRef } from '@welcome-ui/system' import * as S from './Separator.styled' -import { DropdownMenuOptions } from '.' +export type SeparatorProps = CreateWuiProps<'div', Ariakit.MenuSeparatorProps> -export type SeparatorProps = CreateWuiProps< - 'div', - MenuSeparatorProps & { state: DropdownMenuOptions['state'] } -> - -export const Separator = forwardRef<'div', SeparatorProps>(({ state, ...rest }, ref) => { - return +export const Separator = forwardRef<'div', SeparatorProps>((props, ref) => { + return }) diff --git a/packages/DropdownMenu/src/index.tsx b/packages/DropdownMenu/src/index.tsx index addedf5517..5cc4178e35 100644 --- a/packages/DropdownMenu/src/index.tsx +++ b/packages/DropdownMenu/src/index.tsx @@ -1,108 +1,57 @@ import React from 'react' -import { - MenuButton, - MenuInitialState, - MenuOptions, - MenuStateReturn, - Menu as ReakitMenu, - useMenuState, -} from 'reakit' -import { useNextFrame } from '@welcome-ui/utils' -import { As, CreateWuiProps, forwardRef, OmitReakitState, WuiProps } from '@welcome-ui/system' +import * as Ariakit from '@ariakit/react' +import { As, CreateWuiProps, forwardRef, WuiProps } from '@welcome-ui/system' import { Arrow } from './Arrow' import { Item } from './Item' import { Separator } from './Separator' import * as S from './styles' -export interface DropdownMenuOptions { +export interface DropdownMenuOptions extends Ariakit.MenuProps { /** add custom props from styled system on DropdownMenu inner */ innerProps?: WuiProps - state: MenuStateReturn & { - /** - * @deprecated - * will be replace by open on ariakit (reakit v2) - **/ - visible?: MenuOptions['visible'] - /** - * Open the menu on load - */ - open?: MenuOptions['visible'] - } } -export type DropdownMenuProps = CreateWuiProps< - 'div', - OmitReakitState -> +export type DropdownMenuProps = CreateWuiProps<'div', DropdownMenuOptions> const DropdownMenuComponent = forwardRef<'div', DropdownMenuProps>( - ({ children, dataTestId, innerProps = {}, state = {}, ...props }, ref) => { - const { open, visible } = state - const delayedVisible = useNextFrame(open || visible) + ({ children, dataTestId, innerProps = {}, store, gutter = 10, ...rest }, ref) => { + const arrowElement = store.useState('arrowElement') return ( - } + store={store} tabIndex={0} - {...state} - {...props} + {...rest} > - {menuProps => ( - )} - style={{ - ...menuProps.style, - opacity: delayedVisible ? 1 : 0, - }} - > - {children} - - )} - + {children} + ) } ) -export type DropdownMenuStateReturn = MenuStateReturn & { - /** - * @deprecated - * will be replace by open on ariakit (reakit v2) - **/ - visible?: MenuStateReturn['visible'] - open: MenuStateReturn['visible'] -} -export type DropdownMenuInitialState = MenuInitialState & { - /** - * @deprecated - * will be replace by open on ariakit (reakit v2) - **/ - visible?: MenuInitialState['visible'] - /** - * Open the drawer on load - */ - open?: MenuInitialState['visible'] -} +export type UseDropdownMenu = Ariakit.MenuStore +export type UseDropdownMenuOptions = Ariakit.MenuStoreProps -export function useDropdownMenuState(options?: DropdownMenuInitialState): DropdownMenuStateReturn { - const { open, visible, ...restOptions } = options || {} - const dropdownMenuState = useMenuState({ +export function useDropdownMenu(options: UseDropdownMenuOptions = {}): UseDropdownMenu { + const dropdownMenu = Ariakit.useMenuStore({ animated: true, - visible: visible || open, - ...restOptions, + ...options, }) - return { open: dropdownMenuState.visible, ...dropdownMenuState } + return dropdownMenu } -type TriggerProps = { state: MenuStateReturn; children: React.ReactNode; as?: As } +type TriggerProps = { store: UseDropdownMenu; children: React.ReactNode; as?: As } -export const Trigger = forwardRef<'button', TriggerProps>(({ as, state, ...rest }, ref) => { - return +export const Trigger = forwardRef<'button', TriggerProps>(({ as, store, ...rest }, ref) => { + return }) export const DropdownMenu = Object.assign(DropdownMenuComponent, { diff --git a/packages/DropdownMenu/src/styles.ts b/packages/DropdownMenu/src/styles.ts index e81020906c..3ef17639b8 100644 --- a/packages/DropdownMenu/src/styles.ts +++ b/packages/DropdownMenu/src/styles.ts @@ -6,15 +6,11 @@ export const Inner = styled(Box)` ${cardStyles}; ${th('dropdownMenu.inner')}; z-index: 1; - transition: opacity 200ms; + opacity: 0; + transition: opacity 150ms ease-in-out; + ${system}; - &:focus { - outline: none !important; /* important for firefox */ + &[data-enter] { + opacity: 1; } - - &[hidden] { - display: none; - } - - ${system} ` diff --git a/packages/DropdownMenu/tests/index.test.tsx b/packages/DropdownMenu/tests/index.test.tsx index 229328a306..df2fb49710 100644 --- a/packages/DropdownMenu/tests/index.test.tsx +++ b/packages/DropdownMenu/tests/index.test.tsx @@ -2,7 +2,7 @@ import React from 'react' import { renderHook } from '@testing-library/react-hooks' import { render } from '../../../utils/tests' -import { DropdownMenu, useDropdownMenuState } from '../src' +import { DropdownMenu, useDropdownMenu } from '../src' const content = 'jungle' @@ -10,11 +10,11 @@ describe('', () => { it('should render correctly', () => { const dataTestId = 'dropdownMenu' const { - result: { current: menuState }, - } = renderHook(() => useDropdownMenuState()) + result: { current: dropdownMenu }, + } = renderHook(() => useDropdownMenu()) const { getByTestId } = render( - + {content} ) diff --git a/packages/System/src/index.tsx b/packages/System/src/index.tsx index 9547890f3f..45667b282d 100644 --- a/packages/System/src/index.tsx +++ b/packages/System/src/index.tsx @@ -158,9 +158,3 @@ export const forwardRef = ( } export type ExtraSize = number | string - -/* utility type to remove state properties from options (will be corrected when migrating to ariakit) */ -export type OmitReakitState< - ComponentOptions extends { state: unknown }, - ReakitOptions -> = ComponentOptions & Omit diff --git a/yarn.lock b/yarn.lock index 1a2d87e981..c8d551c031 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4331,7 +4331,7 @@ "@pnpm/network.ca-file" "^1.0.1" config-chain "^1.1.11" -"@popperjs/core@^2.5.4", "@popperjs/core@^2.9.2": +"@popperjs/core@^2.9.2": version "2.11.6" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== @@ -6354,11 +6354,6 @@ body-parser@1.20.1: type-is "~1.6.18" unpipe "1.0.0" -body-scroll-lock@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-3.1.5.tgz#c1392d9217ed2c3e237fee1e910f6cdd80b7aaec" - integrity sha512-Yi1Xaml0EvNA0OYWxXiYNqY24AfWkbA6w5vxE7GWxtKfzIbZM+Qw+aSmkgsbWzbHiy/RCSkUZBplVxTA+E4jJg== - boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -16166,36 +16161,6 @@ readdirp@^3.4.0, readdirp@~3.6.0: dependencies: picomatch "^2.2.1" -reakit-system@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/reakit-system/-/reakit-system-0.15.2.tgz#a485fab84b3942acbed6212c3b56a6ef8611c457" - integrity sha512-TvRthEz0DmD0rcJkGamMYx+bATwnGNWJpe/lc8UV2Js8nnPvkaxrHk5fX9cVASFrWbaIyegZHCWUBfxr30bmmA== - dependencies: - reakit-utils "^0.15.2" - -reakit-utils@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/reakit-utils/-/reakit-utils-0.15.2.tgz#b4d5836e534576bfd175171541d43182ad97f2d2" - integrity sha512-i/RYkq+W6hvfFmXw5QW7zvfJJT/K8a4qZ0hjA79T61JAFPGt23DsfxwyBbyK91GZrJ9HMrXFVXWMovsKBc1qEQ== - -reakit-warning@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/reakit-warning/-/reakit-warning-0.6.2.tgz#9c346ae483eb1f284f2088653f90cabd26dbee56" - integrity sha512-z/3fvuc46DJyD3nJAUOto6inz2EbSQTjvI/KBQDqxwB0y02HDyeP8IWOJxvkuAUGkWpeSx+H3QWQFSNiPcHtmw== - dependencies: - reakit-utils "^0.15.2" - -reakit@^1.3.11: - version "1.3.11" - resolved "https://registry.yarnpkg.com/reakit/-/reakit-1.3.11.tgz#c15360ac43e94fbe4291d233af3ac5040428252e" - integrity sha512-mYxw2z0fsJNOQKAEn5FJCPTU3rcrY33YZ/HzoWqZX0G7FwySp1wkCYW79WhuYMNIUFQ8s3Baob1RtsEywmZSig== - dependencies: - "@popperjs/core" "^2.5.4" - body-scroll-lock "^3.1.5" - reakit-system "^0.15.2" - reakit-utils "^0.15.2" - reakit-warning "^0.6.2" - real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"