Skip to content
Open
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
133 changes: 83 additions & 50 deletions src/components/AsyncDropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React from "react"
import AsyncSelect from "react-select/async"
import useTheme from "@material-ui/core/styles/useTheme"

type Props = {
answer?: string,
Expand All @@ -20,56 +21,88 @@ export default ({
autocompleteRequest,
placeholder,
requestUrl
}: Props) => (
<AsyncSelect
placeholder={answer || placeholder}
className="material-survey-selection"
styles={{
menu: provided => ({
...provided,
fontFamily: "Roboto, sans-serif"
}),
container: provided => ({
...provided,
fontFamily: "Roboto, sans-serif"
}),
menuPortal: provided => ({ ...provided, zIndex: 10000 })
}}
loadOptions={async inputValue => {
if (autocompleteRequest) {
return (await autocompleteRequest(requestUrl, inputValue)).map(
({ value, label, subLabel }: any) => ({
value,
label: subLabel ? (
<div
aria-label={label}
>
{label}
}: Props) => {
const MUItheme = useTheme()
return (
<AsyncSelect
placeholder={answer || placeholder}
className="material-survey-selection"
styles={{
menu: provided => ({
...provided,
fontFamily: "Roboto, sans-serif"
}),
container: provided => ({
...provided,
fontFamily: "Roboto, sans-serif"
}),
menuPortal: provided => ({ ...provided, zIndex: 10000 }),
singleValue: provided => ({
...provided,
color: MUItheme.palette.text.primary
}),
option: (provided, { data, isDisabled, isFocused, isSelected }) => ({
...provided,
color: (isFocused || isSelected) ? MUItheme.palette.primary.contrastText : MUItheme.palette.text.primary
})
}}
theme={theme => ({
...theme,
colors: {
...theme.colors,
primary: MUItheme.palette.primary.main,
primary75: MUItheme.palette.primary.light,
primary50: MUItheme.palette.primary.light,
primary25: MUItheme.palette.primary.light,
neutral0: MUItheme.palette.background.paper,
neutral5: MUItheme.palette.grey['50'],
neutral10: MUItheme.palette.grey['100'],
neutral20: MUItheme.palette.grey['200'],
neutral30: MUItheme.palette.grey['300'],
neutral40: MUItheme.palette.grey['400'],
neutral50: MUItheme.palette.grey['500'],
neutral60: MUItheme.palette.grey['600'],
neutral70: MUItheme.palette.grey['700'],
neutral80: MUItheme.palette.grey['800'],
neutral90: MUItheme.palette.grey['900']
}
})}
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be part of a global context or in a single file, in react when you define objects in component props it causes a lot of rerenders- it COULD be a problem from a performance perspective and it's a problem from a DRY perspective.

Copy link
Author

Choose a reason for hiding this comment

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

I understand your concern, however, the theme really would change on some rare occasions, for example, switching between light mode and dark mode.

Is that okay, if I somehow "memorise" the colors object, therefore reduces the re-rendering of the object?

Copy link
Author

Choose a reason for hiding this comment

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

const themeColors = useMemo(() => ({
  primary: MUItheme.palette.primary.main,
  primary75: MUItheme.palette.primary.light,
  primary50: MUItheme.palette.primary.light,
  primary25: MUItheme.palette.primary.light,
  neutral0: MUItheme.palette.background.paper,
  neutral5: MUItheme.palette.grey['50'],
  neutral10: MUItheme.palette.grey['100'],
  neutral20: MUItheme.palette.grey['200'],
  neutral30: MUItheme.palette.grey['300'],
  neutral40: MUItheme.palette.grey['400'],
  neutral50: MUItheme.palette.grey['500'],
  neutral60: MUItheme.palette.grey['600'],
  neutral70: MUItheme.palette.grey['700'],
  neutral80: MUItheme.palette.grey['800'],
  neutral90: MUItheme.palette.grey['900']
}), [MUItheme])
<AsyncSelect
  ...
  theme={theme => ({
    ...theme,
    colors: {
      ...theme.colors,
      ...themeColors
    }
  })}
  ...

loadOptions={async inputValue => {
if (autocompleteRequest) {
return (await autocompleteRequest(requestUrl, inputValue)).map(
({ value, label, subLabel }: any) => ({
value,
label: subLabel ? (
<div
style={{
opacity: 0.7,
fontSize: 12
}}
aria-label={subLabel}
aria-label={label}
>
{subLabel}
{label}
<div
style={{
opacity: 0.7,
fontSize: 12
}}
aria-label={subLabel}
>
{subLabel}
</div>
</div>
</div>
) : (
label
)
})
)
} else {
return [
{
value: "",
label: "No autocompleteRequest callback configured"
}
]
}
}}
menuPortalTarget={document.body}
onChange={({ value }) => onChange(value)}
/>
)
) : (
label
)
})
)
} else {
return [
{
value: "",
label: "No autocompleteRequest callback configured"
}
]
}
}}
menuPortalTarget={document.body}
onChange={({ value }) => onChange(value)}
/>
)
}
32 changes: 32 additions & 0 deletions src/components/DropdownQuestion/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Select from "@material-ui/core/Select"
import ReactSelect from "react-select"
import MenuItem from "@material-ui/core/MenuItem"
import styled from "styled-components"
import useTheme from "@material-ui/core/styles/useTheme"

const SelectedValueContainer = styled.div`
padding: 4px;
Expand All @@ -27,6 +28,8 @@ export default ({
multiple?: boolean,
changeAnswer: Function
}) => {
const MUItheme = useTheme()

const choiceList = choices.map(choice =>
typeof choice === "string" ? { value: choice, text: choice } : choice
)
Expand Down Expand Up @@ -57,8 +60,37 @@ export default ({
container: provided => ({
...provided,
fontFamily: "Roboto, sans-serif"
}),
singleValue: provided => ({
...provided,
color: MUItheme.palette.text.primary
}),
option: (provided, { data, isDisabled, isFocused, isSelected }) => ({
...provided,
color: (isFocused || isSelected) ? MUItheme.palette.primary.contrastText : MUItheme.palette.text.primary
})
}}
theme={theme => ({
...theme,
colors: {
...theme.colors,
primary: MUItheme.palette.primary.main,
primary75: MUItheme.palette.primary.light,
primary50: MUItheme.palette.primary.light,
primary25: MUItheme.palette.primary.light,
neutral0: MUItheme.palette.background.paper,
neutral5: MUItheme.palette.grey['50'],
neutral10: MUItheme.palette.grey['100'],
neutral20: MUItheme.palette.grey['200'],
neutral30: MUItheme.palette.grey['300'],
neutral40: MUItheme.palette.grey['400'],
neutral50: MUItheme.palette.grey['500'],
neutral60: MUItheme.palette.grey['600'],
neutral70: MUItheme.palette.grey['700'],
neutral80: MUItheme.palette.grey['800'],
neutral90: MUItheme.palette.grey['900']
}
})}
isMulti={multiple}
menuPortalTarget={document.body}
options={choiceList.map(c => ({ value: c.value, label: c.text }))}
Expand Down