Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Merge 0f66aaa into ea2578a
Browse files Browse the repository at this point in the history
  • Loading branch information
tinkertrain committed Apr 14, 2021
2 parents ea2578a + 0f66aaa commit 9a66bf1
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/components/ConditionField/ConditionField.AddButton.jsx
Expand Up @@ -75,6 +75,7 @@ const AnimatedComponent = withMotion({
const height = node.clientHeight
node.style.height = 0
node.style.overflow = 'hidden'
node.style.willChange = ''

return animate({
keyframes: [
Expand All @@ -86,6 +87,7 @@ const AnimatedComponent = withMotion({
duration: props.animationDuration,
easing: props.animationEasing,
}).finished.then(() => {
node.style.willChange = ''
node.style.overflow = 'initial'
})
},
Expand All @@ -95,6 +97,7 @@ const AnimatedComponent = withMotion({
const height = node.clientHeight
node.style.height = height
node.style.overflow = 'hidden'
node.style.willChange = ''

return animate({
keyframes: [
Expand Down
2 changes: 2 additions & 0 deletions src/components/DropList/DropList.Combobox.jsx
Expand Up @@ -28,6 +28,7 @@ function Combobox({
selectedItems,
isOpen = false,
items = [],
menuCSS,
handleSelectedItemChange = noop,
renderCustomListItem = null,
toggleOpenedState = noop,
Expand Down Expand Up @@ -123,6 +124,7 @@ function Combobox({
className="DropList DropList__Combobox"
data-cy={dataCy}
variant="combobox"
menuCSS={menuCSS}
{...getComboboxProps()}
>
<InputSearchHolderUI show={items.length > 0}>
Expand Down
7 changes: 6 additions & 1 deletion src/components/DropList/DropList.Select.jsx
Expand Up @@ -23,6 +23,7 @@ function Select({
handleSelectedItemChange = noop,
isOpen = false,
items = [],
menuCSS,
onMenuBlur = noop,
renderCustomListItem = null,
selectedItem = null,
Expand Down Expand Up @@ -122,7 +123,11 @@ function Select({
}

return (
<DropListWrapperUI className="DropList DropList__Select" data-cy={dataCy}>
<DropListWrapperUI
className="DropList DropList__Select"
data-cy={dataCy}
menuCSS={menuCSS}
>
<A11yTogglerUI {...getToggleButtonProps()}>Toggler</A11yTogglerUI>
<MenuListUI
{...getMenuProps({
Expand Down
2 changes: 2 additions & 0 deletions src/components/DropList/DropList.css.js
Expand Up @@ -18,6 +18,8 @@ export const DropListWrapperUI = styled('div')`
* {
box-sizing: border-box;
}
${props => (props.menuCSS ? props.menuCSS : '')};
`

export const MenuListUI = styled('ul')`
Expand Down
6 changes: 5 additions & 1 deletion src/components/DropList/DropList.jsx
Expand Up @@ -36,6 +36,7 @@ function DropListManager({
focusTogglerOnMenuClose = true,
isMenuOpen = false,
items = [],
menuCSS,
onMenuBlur = noop,
onOpenedStateChange = noop,
onSelect = noop,
Expand Down Expand Up @@ -76,7 +77,7 @@ function DropListManager({
const Toggler = decorateUserToggler(toggler)
const DropListVariant = getDropListVariant()

useWarnings({ toggler, withMultipleSelection })
useWarnings({ toggler, withMultipleSelection, menuCSS, tippyOptions })

useDeepCompareEffect(() => {
if (withMultipleSelection) {
Expand Down Expand Up @@ -226,6 +227,7 @@ function DropListManager({
handleSelectedItemChange={handleSelectedItemChange}
isOpen={isOpen}
items={parsedItems}
menuCSS={menuCSS}
onMenuBlur={onMenuBlur}
renderCustomListItem={renderCustomListItem}
selectedItem={selectedItem}
Expand Down Expand Up @@ -283,6 +285,8 @@ DropListManager.propTypes = {
items: PropTypes.arrayOf(
PropTypes.oneOfType([PropTypes.string, itemShape, dividerShape, groupShape])
),
/** Custom css for the Menu */
menuCSS: PropTypes.any,
/** Callback that fires when the menu loses focus */
onMenuBlur: PropTypes.func,
/** Callback that fires whenever the DropList opens and closes */
Expand Down
25 changes: 25 additions & 0 deletions src/components/DropList/DropList.stories.mdx
Expand Up @@ -59,6 +59,31 @@ Sometimes the list needs to be appended to a different DOM context due to access
/>
```

Sometimes when portaling you might need to apply some custom css to the menu but find that adding styles using Styled Components doesn't work (this happens because the styled component can't target the menu as it's no longer in its scope). In these rare ocasions you can use the `menuCSS` prop to add your styles, it accepts the returned value from the [`css` helper from Styled Components](https://styled-components.com/docs/api#css)

```jsx
// import { css } from 'styled-components'

<DropList
items={regularItems}
toggler={<SimpleButton text="Click" />}
tippyOptions={{
appendTo: () => document.body,
}}
menuCSS={css`
width: 134px;
&:hover {
color: salmon;
}
`}
/>
```

> Note: `menuCSS` should only be used in conjuction with `tippyOptions.appendTo`, if not you will see errors in the console. Use regular styled components in any other instance.
<br />

## Example

<Canvas>
Expand Down
26 changes: 26 additions & 0 deletions src/components/DropList/DropList.test.js
@@ -1,6 +1,7 @@
import React from 'react'
import { render, waitFor } from '@testing-library/react'
import user from '@testing-library/user-event'
import { css } from 'styled-components'
import DropList from './DropList'
import { SimpleButton, SelectTag, SplittedButton } from './DropList.togglers'
import {
Expand Down Expand Up @@ -267,6 +268,31 @@ describe('Render', () => {
})
})

test('should be able to pass custom css to the menu when portaling', async () => {
const { queryByText } = render(
<DropList
items={beatles}
tippyOptions={{
appendTo: () => document.body,
}}
toggler={<SimpleButton text="Click" />}
menuCSS={css`
outline: '2px solid salmon';
`}
/>
)

user.click(queryByText('Click'))

await waitFor(() => {
const select = document.querySelector('.DropList__Select')

expect(window.getComputedStyle(select).getPropertyValue('outline')).toBe(
"'2px solid salmon'"
)
})
})

test('should close on ESC', async () => {
const { container, getByRole } = render(
<DropList
Expand Down
16 changes: 13 additions & 3 deletions src/components/DropList/DropList.utils.js
Expand Up @@ -6,7 +6,12 @@ import { ListItemUI, EmptyListUI } from './DropList.css'

// No need to test this helper
/* istanbul ignore next */
export function displayWarnings({ toggler, withMultipleSelection }) {
export function displayWarnings({
toggler,
withMultipleSelection,
menuCSS,
tippyOptions,
}) {
if (
process.env.NODE_ENV !== 'production' &&
process.env.NODE_ENV !== 'test'
Expand All @@ -21,12 +26,17 @@ export function displayWarnings({ toggler, withMultipleSelection }) {
'The Select toggler option should not have withMultipleSelection enabled, it has been disabled for you'
)
}
if (menuCSS != null && tippyOptions.appendTo === undefined) {
console.error(
'menuCSS is only needed when using tippyOptions.appendTo to portal the DropList, please use regular styled components if you need custom styles'
)
}
}
}

export function useWarnings({ toggler, withMultipleSelection }) {
export function useWarnings(props) {
useEffect(() => {
displayWarnings({ toggler, withMultipleSelection })
displayWarnings(props)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}
Expand Down

0 comments on commit 9a66bf1

Please sign in to comment.