Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FX-5652] Migrate Dropdown to TailwindCSS #4499

Merged
merged 23 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/weak-pumas-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@toptal/picasso-dropdown': minor
---

### Dropdown

- change the ClickAwayListener component to be imported from @mui/base
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`ButtonSplit closes menu on click to the item 1`] = `
<svg
class="PicassoSvgArrowDownMinor24-root-29"
class="PicassoSvgArrowDownMinor24-root-24"
style="min-width: 24px; min-height: 24px;"
viewBox="0 0 24 24"
>
Expand Down Expand Up @@ -35,10 +35,10 @@ exports[`ButtonSplit default render 1`] = `
</span>
</button>
<div
class="PicassoDropdown-root block cursor-pointer"
class="items-center block cursor-pointer"
>
<div
class="PicassoDropdown-anchor"
class="inline-flex items-center cursor-pointer"
>
<button
aria-disabled="false"
Expand Down Expand Up @@ -71,7 +71,7 @@ exports[`ButtonSplit default render 1`] = `

exports[`ButtonSplit renders arrow down icon for a closed menu 1`] = `
<svg
class="PicassoSvgArrowDownMinor16-root-29"
class="PicassoSvgArrowDownMinor16-root-24"
style="min-width: 16px; min-height: 16px;"
viewBox="0 0 16 16"
>
Expand All @@ -83,7 +83,7 @@ exports[`ButtonSplit renders arrow down icon for a closed menu 1`] = `

exports[`ButtonSplit renders arrow up icon for an opened menu 1`] = `
<svg
class="PicassoSvgArrowDownMinor16-root-29 rotate-180"
class="PicassoSvgArrowDownMinor16-root-24 rotate-180"
style="min-width: 16px; min-height: 16px;"
viewBox="0 0 16 16"
>
Expand Down
3 changes: 2 additions & 1 deletion packages/base/Dropdown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso#readme",
"dependencies": {
"@mui/base": "5.0.0-beta.40",
"@toptal/picasso-paper": "4.0.0",
"@toptal/picasso-popper": "1.0.3",
"@toptal/picasso-utils": "1.0.3",
Expand All @@ -39,8 +40,8 @@
},
"devDependencies": {
"@toptal/picasso-provider": "5.0.0",
"@toptal/picasso-test-utils": "1.1.1",
"@toptal/picasso-tailwind-merge": "2.0.0",
"@toptal/picasso-test-utils": "1.1.1",
"popper.js": "^1.16.1"
},
"exports": {
Expand Down
51 changes: 30 additions & 21 deletions packages/base/Dropdown/src/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import type { HTMLAttributes, ReactElement, ReactNode, Ref } from 'react'
import React, { forwardRef, useContext, useRef, useState } from 'react'
import ClickAwayListener from '@material-ui/core/ClickAwayListener'
import Grow from '@material-ui/core/Grow'
import type { PopperPlacementType } from '@material-ui/core/Popper'
import type { PopperOptions } from 'popper.js'
import type { Theme } from '@material-ui/core/styles'
import { makeStyles } from '@material-ui/core/styles'
import cx from 'classnames'
import type { StandardProps } from '@toptal/picasso-shared'
import type {
DeprecatedSpacingType,
Expand All @@ -16,12 +12,21 @@ import { makeResponsiveSpacingProps } from '@toptal/picasso-provider'
import { Popper } from '@toptal/picasso-popper'
import { Paper } from '@toptal/picasso-paper'
import { noop } from '@toptal/picasso-utils'
import { twJoin, twMerge } from '@toptal/picasso-tailwind-merge'
import { ClickAwayListener } from '@mui/base/ClickAwayListener'

import type { StyleProps } from './styles'
import styles from './styles'
import { contentClass } from './styles'

type ContentOverflowType = 'scroll' | 'visible'

type StyleProps = {
/** Control content element style */
contentStyle?: {
height?: string
maxHeight?: string
}
}

interface InternalProps
extends StandardProps,
HTMLAttributes<HTMLDivElement>,
Expand Down Expand Up @@ -49,6 +54,8 @@ interface InternalProps
/** Sets the desired behavior for an element's overflow */
contentOverflow?: ContentOverflowType
popperContainer?: HTMLElement
/** Sets styles for the inner wrapper */
classes?: { popper?: string; content?: string }
TomasSlama marked this conversation as resolved.
Show resolved Hide resolved
}

type PropsWithBaseSpacing = InternalProps & {
Expand Down Expand Up @@ -94,13 +101,6 @@ export const useDropdownContext = () => {
return context
}

const useStyles = makeStyles<
Theme,
PropsWithBaseSpacing | PropsWithDeprecatedSpacing
>(styles, {
name: 'PicassoDropdown',
})

const useResponsiveProps = makeResponsiveSpacingProps(
['margin-top', 'margin-bottom', 'margin-left', 'margin-right'] as const,
'PicassoDropdown-Responsive'
Expand Down Expand Up @@ -147,7 +147,6 @@ export const Dropdown: DropdownProps = forwardRef<
contentOverflow = 'scroll',
...rest
} = props
const classes = useStyles(props)

const contentRef = useRef<HTMLDivElement>(null)
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | undefined>()
Expand Down Expand Up @@ -238,7 +237,7 @@ export const Dropdown: DropdownProps = forwardRef<
close: () => forceClose(),
}

const handleClickAway = (event: React.MouseEvent<Document>) => {
const handleClickAway = (event: MouseEvent | TouchEvent) => {
const target = event.target

const isAnchorTapEvent =
Expand All @@ -255,16 +254,23 @@ export const Dropdown: DropdownProps = forwardRef<
<div
{...rest}
ref={ref}
className={cx(classes.root, className)}
className={twMerge('flex items-center', className)}
style={style}
>
<div className={classes.anchor} onClick={handleAnchorClick}>
<div
className='inline-flex items-center cursor-pointer'
onClick={handleAnchorClick}
>
{typeof children === 'function' ? children({ isOpen }) : children}
</div>

{(isOpen || keepMounted) && (
<Popper
className={cx(classes.popper, responsiveClasses)}
className={twJoin(
'shadow-2',
externalClasses?.popper,
TomasSlama marked this conversation as resolved.
Show resolved Hide resolved
responsiveClasses
)}
anchorEl={anchorEl ?? null}
popperOptions={{
onCreate: focus,
Expand Down Expand Up @@ -293,9 +299,12 @@ export const Dropdown: DropdownProps = forwardRef<
<Grow in={isOpen} appear>
<Paper
style={contentStyle}
className={cx(classes.content, {
[classes.contentVisible]: contentOverflow === 'visible',
})}
className={twMerge(
contentOverflow === 'visible'
? contentClass.contentVisible
: contentClass.content,
externalClasses?.content
)}
onKeyDown={handleContentKeyDown}
elevation={0}
>
Expand Down
20 changes: 10 additions & 10 deletions packages/base/Dropdown/src/Dropdown/__snapshots__/test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ exports[`Dropdown renders 1`] = `
class="Picasso-root"
>
<div
class="PicassoDropdown-root"
class="flex items-center"
>
<div
class="PicassoDropdown-anchor"
class="inline-flex items-center cursor-pointer"
>
Open Dropdown
<span
Expand Down Expand Up @@ -37,10 +37,10 @@ exports[`Dropdown should render menu 1`] = `
class="Picasso-root"
>
<div
class="PicassoDropdown-root"
class="flex items-center"
>
<div
class="PicassoDropdown-anchor"
class="inline-flex items-center cursor-pointer"
>
Open Dropdown
<span
Expand All @@ -58,14 +58,14 @@ exports[`Dropdown should render menu 1`] = `
</div>
</div>
<div
class="PicassoPopper-root PicassoDropdown-popper"
class="PicassoPopper-root shadow-2"
role="tooltip"
style="position: absolute; top: 0px; left: 0px;"
x-placement="bottom-end"
>
<div>
<div
class="bg-white shadow-0 transition-shadow duration-300 delay-0 PicassoDropdown-content"
class="bg-white shadow-0 transition-shadow duration-300 delay-0 overflow-y max-h [@media(max-height:585px)]:max-h-[calc(50vh [@media(max-height:585px)]:md:max-h-[calc(50vh"
style="opacity: 1; transform: scale(1, 1); transition: opacity 0ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,transform 0ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;"
>
<div>
Expand Down Expand Up @@ -166,10 +166,10 @@ exports[`Dropdown should render menu with focus 1`] = `
class=""
>
<div
class="PicassoDropdown-root"
class="flex items-center"
>
<div
class="PicassoDropdown-anchor"
class="inline-flex items-center cursor-pointer"
>
Open Dropdown
<span
Expand All @@ -188,14 +188,14 @@ exports[`Dropdown should render menu with focus 1`] = `
</div>
</div>
<div
class="PicassoPopper-root PicassoDropdown-popper"
class="PicassoPopper-root shadow-2"
role="tooltip"
style="position: absolute; top: 0px; left: 0px; transform: translate3d(NaNpx, NaNpx, 0); will-change: transform;"
x-placement="bottom-end"
>
<div>
<div
class="bg-white shadow-0 transition-shadow duration-300 delay-0 PicassoDropdown-content"
class="bg-white shadow-0 transition-shadow duration-300 delay-0 overflow-y max-h [@media(max-height:585px)]:max-h-[calc(50vh [@media(max-height:585px)]:md:max-h-[calc(50vh"
style="opacity: 1; transform: scale(1, 1); transition: opacity 0ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,transform 0ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;"
>
<div>
Expand Down
69 changes: 14 additions & 55 deletions packages/base/Dropdown/src/Dropdown/styles.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,17 @@
import type { Theme } from '@material-ui/core/styles'
import { createStyles } from '@material-ui/core/styles'
export const contentClass: Record<'content' | 'contentVisible', string[]> = {
content: [
'overflow-y-auto',

export type StyleProps = {
/** Control content element style */
contentStyle?: {
height?: string
maxHeight?: string
}
}

export default ({ screens, shadows, palette }: Theme) =>
createStyles({
root: {
display: 'flex',
alignItems: 'center',
},
anchor: {
display: 'inline-flex',
alignItems: 'center',
cursor: 'pointer',
},
content: {
fontSize: 'inherit',
background: palette.common.white,

maxHeight: '14.75rem', // 6.5 lines of menu to show
overflowY: 'auto',
'max-h-[14.75rem]',
'[@media(max-height:585px)]:max-h-[calc(50vh-3rem)]',
'[@media(max-height:585px)]:md:max-h-[calc(50vh-3.5rem)]',
],
contentVisible: [
'max-h-screen md:max-h-none ',

// height under which maxHeight menu starts to overflow
// and needs to reduce height dynamically to avoid overflow
'@media screen and (max-height: 585px)': {
maxHeight: 'calc(50vh - 3rem)', // half of viewport minus header and anchor
'overflow-y-scroll md:overflow-y-hidden',

[screens('md', 'lg', 'xl')]: {
maxHeight: 'calc(50vh - 3.5rem)', // half of screen minus header and anchor
},
},
},
popper: {
boxShadow: shadows[2],
},
contentVisible: {
// Basically a whole content of a dropdown will be shown without a vertical scrollbar inside the dropdown
maxHeight: 'none',

// Will show a whole content on the `xs` and `sm` screens with a vertical scrollbar if needed
// For non desktop devices better if we have a scrollbar when a dropdown content is pretty long
[screens('xs', 'sm')]: {
overflowY: 'scroll',
maxHeight: '100vh',
},
'@media screen and (max-height: 585px)': {
overflowY: 'scroll',
maxHeight: '100vh',
},
},
})
'[@media(max-height:585px)]:max-h-screen',
'[@media(max-height:585px)]:overflow-y-scroll',
],
}
6 changes: 4 additions & 2 deletions packages/base/Page/src/PageHamburger/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ export default () => {
return createStyles({
root: {
[headerBreakingPointXL]: {
display: 'none',
//TODO: add important property here to overwrite the styles in Dropdown component. Should be removed after migrating to TailwindCSS in task https://toptal-core.atlassian.net/browse/FX-5688
display: 'none !important',
},
},
popper: {
Expand All @@ -16,7 +17,8 @@ export default () => {
pointerEvents: 'none',
},
hidden: {
display: 'none',
//TODO: add important property here to overwrite the styles in Dropdown component. Should be removed after migrating to TailwindCSS in task https://toptal-core.atlassian.net/browse/FX-5688
display: 'none !important',
},
})
}
Loading
Loading