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

Capability of using Downshift for Select component #15078

Closed
2 tasks done
raymondsze opened this issue Mar 27, 2019 · 13 comments
Closed
2 tasks done

Capability of using Downshift for Select component #15078

raymondsze opened this issue Mar 27, 2019 · 13 comments
Labels
component: select This is the name of the generic UI component, not the React module! discussion

Comments

@raymondsze
Copy link
Contributor

raymondsze commented Mar 27, 2019

Apart from AutoComplete, downshift could be used to implement a dropdown component with getToggleProps.

I would like to use downshift instead of the original implementation of Select (TextField) component.

The main purpose I would like to have this feature is to implement

  1. infinte-scroll dropdown (with react-virtualized or similar tools)
  2. modal select (which is more user friendly to mobile device)

What I need is to keep the ui looks & feel of what Select have.

I have tried to set the open and onOpen of SelectProps to make the open controlled by myself. But Select force me to put at least one child to the component.

Also, if I click on the TextField, the TextField is highlighted as usual (focused state) but never get blur if I mark the open prop as false.

Another attempt is I try to implement a component looks similar to Select but without Menu and any dropdown related event callback. But I found it is too hard to do except clone the codes from the @material-ui/core package.

Any advices / workaround on doing this?
Or should we have a pure Select like component without any dropdown behaviour or pass a props to Select indicate that we would implement the dropdown ourself?

And just a question. What is the design principle of Select and RadioGroup, since these component make use of React.cloneElement heavily and somehow assume the children must be MenuItem or FormControlLabel/Radio. Select is more complicated as it grab the children of MenuItem as default "renderValue", the "renderValue" behaviour could be different if multiple is specified as true due to .join(','). And... we have RadioGroup but we don't have CheckboxGroup. If array value is rare, why we have Select that with "multiple" prop.....

Thanks.

  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 🤔

Current Behavior 😯

Examples 🌈

Context 🔦

@raymondsze
Copy link
Contributor Author

raymondsze commented Mar 27, 2019

Here is what i did right now to make a Select like component.
PS: I didn't extract the style to makeStyle, but rough idea..
Not sure whether it is right way to go.

const InputComponent = ({ className, 'aria-invalid': _, inputRef, ...props }: any) => (
  <div tabIndex={0} ref={inputRef} className={className} style={{ height: '1.1875em', cursor: 'pointer' }}>
    Option {props.value + 1}
    <input {...props} type="hidden" />
    <ArrowDownIcon
      style={{ position: 'absolute', right: 0, top: 'calc(50% - 12px)' }}
      color="action"
    />
  </div>
);

const Dropdown = () => (
  <Downshift>
            {({
              getToggleButtonProps,
              getMenuProps,
              getItemProps,
              isOpen,
              highlightedIndex,
              selectedItem,
              closeMenu,
            }) => (
              <div>
                <MuiTextField
                  variant="filled"
                  label="Mock Dropdown"
                  value={selectedItem}
                  style={{ width: 160, cursor: 'pointer' }}
                  {...getToggleButtonProps()}
                  InputLabelProps={{ shrink: true }}
                  InputProps={{
                    inputRef,
                    inputComponent: InputComponent,
                  }}
                />
                <Popper open={isOpen} anchorEl={inputRef.current} style={{ zIndex: 1300 }}>
                  <Grow in={isOpen}>
                    <Paper elevation={8} style={{ width: inputRef.current ? inputRef.current.clientWidth : undefined }}>
                      <List {...getMenuProps({}, { suppressRefError: true })}>
                        {new Array(2).fill(null).map((_, i) => (
                          <ListItem
                            {...getItemProps({ key: i, item: i, index: i })}
                            style={{ fontWeight: selectedItem === i ? 500 : 300 }}
                            selected={highlightedIndex === i}
                            button={true}
                          >
                            Option {i + 1}
                          </ListItem>
                        ))}
                      </List>
                    </Paper>
                  </Grow>
                </Popper>
              </div>
            )}
          </Downshift>
);

@hungrymonkey
Copy link

A few things.
Downshift is a render prop library. Downshift is telling you to draw itself.

I would highly recommend you bind onSelect, onStateChange, and stateReducer to grok Downshift internal states. I believe have downshift has around 15 states. You can fine grain control over state change with stateReducer.

https://github.com/downshift-js/downshift/blob/master/src/stateChangeTypes.js

/*
 * All possible downshift states
 * 0: "unknown"
 * 1: "mouseUp"
 * 2: "itemMouseEnter"
 * 3: "keyDownArrowUp"
 * 4: "keyDownArrowDown"
 * 5: "keyDownEscape"
 * 6: "keyDownEnter"
 * 7: "clickItem"
 * 8: "blurInput"
 * 9: "changeInput"
 * 10: "keyDownSpaceButton"
 * 11: "clickButton"
 * 12: "blurButton"
 * 13: "controlledPropUpdatedSelectedItem"
 * 14: "touchStart"
 */

On the other note: I would recommend you warp your drop down in a normal div tag.
downshift-js/downshift#443
Material UI breaks downshift expected ref behavior. You cannot select it on IOS.

@raymondsze
Copy link
Contributor Author

raymondsze commented Apr 10, 2019

Actually I would like to ask the ability to make the Select component Menu controllable.
Here is the problems:
Select ask me to pass the children, the children props is mandatory. But if I would like to use Downshift, the menu is rendered externally, I don't need any children there. Even the open and onOpen props are passed, this behaviour is still cannot be changed.

Here is the codes I finally work out to make it works.
It's long but hope you get the idea what I trying to do.

  1. Convert downshift to hook version (It is optional, but hook is easier to me)
import React, { useContext } from 'react';
import Downshift, { DownshiftProps, ControllerStateAndHelpers } from 'downshift';
import { StyledComponentProps } from '@material-ui/core/styles';
import { createStyles, withStyles, WithStyles } from '@material-ui/styles';

export * from 'downshift';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

const styles = createStyles({
  root: { display: 'inline' },
});

export type DownshiftClassKey = keyof WithStyles<typeof styles>['classes'];

interface DownshiftWrapperProps extends Omit<DownshiftProps<any>, 'children'>, StyledComponentProps<DownshiftClassKey> {
  id?: string;
  children: React.ReactNode;
};

export interface DownshiftWrapperInnerProps extends Omit<DownshiftWrapperProps, 'classes'>, WithStyles<DownshiftClassKey> {};

const Context = React.createContext<ControllerStateAndHelpers<any> | null>(null);

export const useDownshift = () => useContext(Context);

const stateReducer: DownshiftProps<any>['stateReducer'] = (state, changes) => {
  switch (changes.type) {
    case Downshift.stateChangeTypes.itemMouseEnter: return state;
  }
  return changes;
}

const DownshiftWrapper = (props: DownshiftWrapperInnerProps) => {
  const { id, children, classes, ...rest } = props;
  return (
    <Downshift
      id={id}
      labelId={`${id}-label`}
      inputId={`${id}-input`}
      menuId={`${id}-menu`}
      stateReducer={stateReducer}
      {...rest}
    >
      {(stateAndHelpers) => (
        <div className={classes.root}>
          <Context.Provider value={stateAndHelpers}>
            {children}
          </Context.Provider>
        </div>
      )}
    </Downshift>
  );
};

export type DownshiftProps = DownshiftWrapperProps;
export default withStyles(styles)(DownshiftWrapper) as React.ComponentType<DownshiftWrapperProps>;
  1. Clone a SelectInput like component but children is not necessary (Here I added some custom styling to make it like MWC)
import React from 'react';
import clsx from 'clsx';
import { Theme, StyledComponentProps } from '@material-ui/core/styles';
import { createStyles, withStyles, WithStyles } from '@material-ui/styles';
import ArrowDropdown from '../internal/svg-icons/ArrowDropdown';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

const styles = (theme: Theme) => createStyles({
  /* Styles applied to the `Input` component `root` class. */
  root: {
    position: 'relative',
    width: '100%',
    outline: 'none',
  },
  select: {
    '-moz-appearance': 'none', // Reset
    '-webkit-appearance': 'none', // Reset
    // When interacting quickly, the text can end up selected.
    // Native select can't be selected either.
    userSelect: 'none',
    paddingRight: 32,
    borderRadius: 0, // Reset
    height: '1.1875em', // Reset (19px), match the native input line-height
    width: 'calc(100% - 32px)',
    minWidth: 16, // So it doesn't collapse.
    cursor: 'pointer',
    '&:focus': {
      // Show that it's not an text input
      backgroundColor:
        theme.palette.type === 'light' ? 'rgba(0, 0, 0, 0.05)' : 'rgba(255, 255, 255, 0.05)',
      borderRadius: 0, // Reset Chrome style
    },
    // Remove IE 11 arrow
    '&::-ms-expand': {
      display: 'none',
    },
    '&$disabled': {
      cursor: 'default',
    },
    '&$open': {
      backgroundColor: 'inherit',
      cursor: 'default',
    },
  },
  /* Styles applied to the `Input` component if `variant="filled"`. */
  filled: {
    width: 'calc(100% - 44px)',
  },
  /* Styles applied to the `Input` component if `variant="outlined"`. */
  outlined: {
    width: 'calc(100% - 46px)',
    borderRadius: theme.shape.borderRadius,
  },
  /* Styles applied to the `Input` component `selectMenu` class. */
  selectMenu: {
    width: 'auto', // Fix Safari textOverflow
    height: 'auto', // Reset
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    overflow: 'hidden',
    minHeight: '1.1875em', // Reset (19px), match the native input line-height
  },
  /* Styles applied to the `Input` component `disabled` class. */
  disabled: {},
  icon: {
    transition: theme.transitions.create('transform', {
      duration: theme.transitions.duration.shortest,
    }),
    // We use a position absolute over a flexbox in order to forward the pointer events
    // to the input.
    position: 'absolute',
    right: 8,
    top: 'calc(50% - 12px)', // Center vertically
    color: theme.palette.action.active,
    'pointer-events': 'none', // Don't block pointer events on the select under the icon.
    '&$open': {
      color: theme.palette.primary.main,
      transform: 'rotate(180deg) translateY(-5px)',
    },
  },
  open: {},
});

export type SelectInputClassKey = keyof WithStyles<typeof styles>['classes'];

export interface SelectInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value'>, StyledComponentProps<SelectInputClassKey> {
  inputRef?: React.Ref<any> | React.RefObject<any>;
  value?: Array<string | number | boolean> | string | number | boolean;
  disabled?: boolean;
  open?: boolean;
  variant?: 'filled' | 'outlined' | 'standard';
  renderValue(value?: Array<string | number | boolean> | string | number | boolean): React.ReactNode;
  SelectDisplayProps?: React.HTMLAttributes<HTMLDivElement>;
};

export interface SelectInputInnerProps extends Omit<SelectInputProps, 'classes'>, WithStyles<SelectInputClassKey> {};

const SelectInput = React.forwardRef<HTMLDivElement, SelectInputInnerProps>(
  (function SelectInput(props: SelectInputInnerProps, ref: React.Ref<HTMLDivElement>) {
    const {
      open,
      inputRef,
      className,
      classes,
      name,
      value,
      disabled,
      variant,
      readOnly,
      renderValue,
      required,
      placeholder,
      type,
      SelectDisplayProps,
      onClick,
      onFocus,
      onBlur,
      onKeyDown,
      onKeyUp,
      ...rest
    } = props;

    const buttonProps = {
      className: clsx(
        classes.select,
        classes.selectMenu,
        {
          [classes.disabled]: disabled,
          [classes.filled]: variant === 'filled',
          [classes.outlined]: variant === 'outlined',
          [classes.open]: open,
        },
        className,
      ),
      onFocus,
      onBlur,
      onKeyDown,
      onKeyUp,
      disabled,
      ...SelectDisplayProps,
    } as any;
  
    return (
      <div ref={ref} className={classes.root}>
        <div
          id={name ? `select-${name}` : undefined}
          tabIndex={0}
          ref={inputRef}
          {...buttonProps}
        >
          {renderValue(value)}
          <input
            name={name}
            value={Array.isArray(value) ? value.join(',') : value}
            type="hidden"
            {...rest as any}
          />
          <ArrowDropdown
            className={clsx(classes.icon, { [classes.open]: open })}
          />
        </div>
      </div>
    )
  }) as React.SFC<SelectInputInnerProps>,
);

export default withStyles(styles)(SelectInput) as React.ComponentType<SelectInputProps>;
  1. Write a TextFIeld that integrated with downshift hook, and make the inputComponent to SelectInput
import React from 'react';
import { SelectProps } from '@material-ui/core/Select';
import TextField, {
  TextFieldClassKey,
  StandardTextFieldProps,
  FilledTextFieldProps,
  OutlinedTextFieldProps,
} from '@material-ui/core/TextField';
import { useDownshift } from '../Downshift';
import SelectInput from './SelectInput';

export type SelectFieldClassKey = TextFieldClassKey;

interface SelectBaseProps {
  renderValue: SelectProps['renderValue'];
  SelectDisplayProps?: React.HTMLAttributes<HTMLDivElement>;
};

export interface StandardSelectFieldProps extends StandardTextFieldProps, SelectBaseProps {};
export interface OutlinedSelectFieldProps extends OutlinedTextFieldProps, SelectBaseProps {};
export interface FilledSelectFieldProps extends FilledTextFieldProps, SelectBaseProps {};

export type SelectFieldProps =
  StandardSelectFieldProps |
  OutlinedSelectFieldProps |
  FilledSelectFieldProps;

const SelectField: React.SFC<any> = props => {
  const { open: openProp, value: valueProp, variant, renderValue, SelectDisplayProps, ...rest } = props;
  const downShift = useDownshift();

  const open = (typeof openProp !== 'undefined') ? openProp : (downShift && downShift.isOpen);
  const value = (typeof valueProp !== 'undefined') ? valueProp : (downShift && downShift.selectedItem);
  const getToggleButtonProps = (downShift && downShift.getToggleButtonProps);

  const handleKeyDown = (event: React.KeyboardEvent) => {
    (event.key === 'Enter') && downShift && downShift.toggleMenu();
  }

  return (
    <TextField
      value={value}
      variant={variant as any}
      {...getToggleButtonProps && getToggleButtonProps({
        onKeyDown: handleKeyDown,
      })}
      {...rest as any}
      InputProps={{
        inputComponent: SelectInput,
        ...rest.InputProps,
        inputProps: {
          open,
          variant,
          renderValue,
          SelectDisplayProps,
          ...rest.InputProps && rest.InputProps.inputProps,
        },
      }}
    />
  );
};

export default SelectField;
  1. Write a Select Popper that integrated with downshift hook
import React from 'react';
import Popper, { PopperProps } from '@material-ui/core/Popper';
import { PopoverProps } from '@material-ui/core/Popover';
import Paper, { PaperProps } from '@material-ui/core/Paper';
import Grow from '@material-ui/core/Grow';
import { StyledComponentProps } from '@material-ui/core/styles';
import { createStyles, withStyles, WithStyles } from '@material-ui/styles';

import { useDownshift } from '../Downshift';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

export const styles = createStyles({
  root: {
    zIndex: 1300,
  },
});

export type SelectPopperClassKey = keyof WithStyles<typeof styles>['classes'];

export interface SelectPopperProps extends Partial<PopperProps>, StyledComponentProps<SelectPopperClassKey> {
  open?: boolean;
  anchorEl: HTMLElement | null;
  children: React.ReactNode;
  PaperProps?: Partial<PaperProps>;
  TransitionComponent?: PopoverProps['TransitionComponent'];
  transitionDuration?: PopoverProps['transitionDuration'];
  TransitionProps?: PopoverProps['TransitionProps'];
};

export interface SelectPopperInnerProps extends Omit<SelectPopperProps, 'classes'>, WithStyles<SelectPopperClassKey> {};

const SelectPopper: React.SFC<SelectPopperInnerProps> = ({
  classes,
  open: openProp,
  anchorEl,
  children,
  PaperProps,
  TransitionComponent,
  transitionDuration,
  TransitionProps,
  ...rest
}) => {
  const Transition = TransitionComponent || Grow;
  const downShift = useDownshift();
  const open = (typeof openProp !== 'undefined') ? openProp : (downShift ? downShift.isOpen : false);
  const getMenuProps = downShift && downShift.getMenuProps;

  return (
    <Popper className={classes.root} open={!!open} anchorEl={anchorEl} {...rest}>
      <Transition
        in={open}
        timeout={transitionDuration}
        {...TransitionProps}
      >
        <Paper
          elevation={8}
          style={{
            minWidth: anchorEl ? anchorEl.clientWidth : undefined,
            ...PaperProps && PaperProps.style
          }}
          {...getMenuProps && getMenuProps({}, { suppressRefError: true })}
          {...PaperProps}
        >
          {children}
        </Paper>
      </Transition>
    </Popper>
  );
};

export default withStyles(styles)(SelectPopper) as React.ComponentType<SelectPopperProps>;
  1. Write a Leaf Menu Item
import React, { useEffect } from 'react';
import clsx from 'clsx';
import MenuItem, { MenuItemProps, MenuItemClassKey } from '@material-ui/core/MenuItem';
import { Theme, StyledComponentProps } from '@material-ui/core/styles';
import { createStyles, withStyles, WithStyles } from '@material-ui/styles';
import { useDownshift } from '../Downshift';

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

export const styles = (theme: Theme) => createStyles({
  root: {},
  gutters: {},
  selected: {},
});

export type SelectItemClassKey = keyof WithStyles<typeof styles>['classes'] | MenuItemClassKey;

export interface SelectItemProps extends Omit<MenuItemProps, 'classes'> {
  classes?: StyledComponentProps<SelectItemClassKey>['classes'];
  highlighted?: boolean;
  index: number;
}

export interface SelectItemInnerProps extends Omit<SelectItemProps, 'classes'>, WithStyles<SelectItemClassKey> {};

const SelectItem: React.SFC<SelectItemInnerProps> = props => {
  const {
    index,
    color,
    selected: selectedProp,
    highlighted: highlightedProp,
    value,
    className,
    classes,
    ...rest
  } = props;

  const downShift = useDownshift();
  const highlighted = (typeof highlightedProp !== 'undefined') ? highlightedProp : (downShift && (downShift.highlightedIndex === index));
  const selected = (typeof selectedProp !== 'undefined') ? selectedProp : (downShift && (downShift.selectedItem === value));
  const getItemProps = downShift && downShift.getItemProps;

  useEffect(() => {
    if (downShift && selected) downShift.setHighlightedIndex(index);
  }, [selected]);

  const itemProps = {
    index,
    value,
    item: value,
    className,
    ...rest,
  };

  return (
    <MenuItem
      classes={classes}
      selected={highlighted}
      {...getItemProps && getItemProps({ index, item: value })}
      {...itemProps}
    />
  );
}

export default withStyles(styles)(SelectItem) as React.ComponentType<SelectItemProps>;
  1. Now I can compose my Select Component as I want
import React from 'react';
import List from '@material-ui/core/List';
import RootRef from '@material-ui/core/RootRef';
import SelectField, {
  SelectFieldClassKey,
  SelectFieldProps,
} from '../SelectField';
import Downshift, { DownshiftProps } from '../Downshift/Downshift';
import SelectPopper, { SelectPopperProps } from '../SelectPopper';

export type DownshiftSelectClassKey = SelectFieldClassKey;

export type DownshiftSelectFieldProps = SelectFieldProps & {
  value: any;
  DownshiftProps?: DownshiftProps;
  SelectPopperProps?: SelectPopperProps;
};

const DownshiftSelectField: React.SFC<DownshiftSelectFieldProps> = props => {
  const [popperNode, setPopperNode] = React.useState<HTMLDivElement | null>(null);

  const { id, value, DownshiftProps, SelectPopperProps, children: childrenProp, ...other } = props;
  const handleRef = (node: HTMLDivElement) => setPopperNode(node);

  return (
    <Downshift
      id={id}
      initialSelectedItem={value}
      {...DownshiftProps}
    >
      <RootRef rootRef={handleRef}>
        <SelectField {...other} />
      </RootRef>
      <SelectPopper anchorEl={popperNode} {...SelectPopperProps}>
        <List>{childrenProp}</List>
      </SelectPopper>
    </Downshift>
  );
}

export default DownshiftSelectField;

And what I would like to get rid of is the SelectInput component.
I think Context + Hook combo would be the trend that I could prevent the problems introduced by RenderProps and Hoc especially the props drilling issue. Just like that current material-ui v4 Radio did.

Currently the Select component main issue is it assuming the children must contain a prop called value, and Menu also relying on children to make the keyboard event works.
It is not possible to integrate the Select component with other library like Downshift, react-virtualized, etc.

Actually if I use third party library like Downshift, the extra behaviour of Select component is mean nothing to me (it may be meaningful to others). So what I need is a static component that looks similar to what Select component but without any event binding (or optional). The closest solution is to pass a endAdornment with value DropdownIcon and mark the component prop to button.

@cvanem
Copy link
Contributor

cvanem commented May 1, 2019

@raymondsze Have you seen mui-downshift package yet? This is what I use.

@raymondsze
Copy link
Contributor Author

@cvanem
mui-downshift is good for general usage, but actually what I want is a generic solution that I can apply either the Downshift or Material-UI current MenuItem behaviour (Hook is one of possible solution) to any item I want.
For example, modal select or even more complex selections ui component.
Downshift is a library could achieve that, but not easy to integrate with MaterialUI "Select" component. Other component are fine, like the AutoComplete example shown in Material UI website.

@eps1lon
Copy link
Member

eps1lon commented May 14, 2019

Is this a proposal for different implementation of Select, are features lacking or is the integration with downshift lacking? Did you have a look at https://next.material-ui.com/components/autocomplete/#downshift?

@eps1lon eps1lon added component: select This is the name of the generic UI component, not the React module! new feature New feature or request status: waiting for author Issue with insufficient information labels May 14, 2019
@raymondsze
Copy link
Contributor Author

raymondsze commented May 14, 2019

@eps1lon
Material UI have example to integrate with Downshift using TextField or equivalent.

However, Select requires Menu and MenuItem to work. As I remember, the children is required for Select Component. Let's say what if I don't want the Menu, but a popup Dialog with MenuItem inside the Dialog? I would like to preserve the Look & Feel of Select component (Material Design) but with different behaviour (for example, integrate with Downshift).

You may say inputAdornment could do the Dropdown Icon, but I found that they are totally different and not easy to do the same.

So, I think it should be a proposal for different implementation of Select (Maybe?).

@eps1lon
Copy link
Member

eps1lon commented May 14, 2019

Let's say what if I don't want the Menu, but a popup Dialog with MenuItem inside the Dialog? I would like to preserve the Look & Feel of Select component (Material Design) but with different behaviour (for example, integrate with Downshift).

That sounds like bad UX. Dialogs are usually very disruptive elements and should be used as rarely as possible. Do you have some mock implementation that I can play with? Right now I don't understand what issue you're trying to solve.

@raymondsze
Copy link
Contributor Author

Let's say what if I don't want the Menu, but a popup Dialog with MenuItem inside the Dialog? I would like to preserve the Look & Feel of Select component (Material Design) but with different behaviour (for example, integrate with Downshift).

That sounds like bad UX. Dialogs are usually very disruptive elements and should be used as rarely as possible. Do you have some mock implementation that I can play with? Right now I don't understand what issue you're trying to solve.

Dialog is bad UX for desktop, but reasonable for Mobile device (What I mean here is 'full-screen' Dialog).
You could simplify my issue as "How could we integrate with downshift to make a dropdown component with same looks and feel as Select component?".

@eps1lon eps1lon added discussion and removed new feature New feature or request status: waiting for author Issue with insufficient information labels May 14, 2019
@eps1lon
Copy link
Member

eps1lon commented May 14, 2019

So this is more of a usage question? Sounds like this is more appropriate for StackOverflow or Spectrum unless you have a conrete proposal for an integration demo. Otherwise I don't think this should be part of the Select component which has a pretty clear definition on the web. Making it work like a fullscreen dialog on mobile is not necessarily part of a select widget.

@raymondsze
Copy link
Contributor Author

Nope, from my point of view. The current implementation of Select does not allow me to integrate with Downshift. Full screen dialog is just an example of usecase.

Basically, here is what I need.

  1. I would like to use the Downshift behaviour with Material UI TextField (select=true) or Material UI Select Component. The reason behind is the default Select behaviour does not fit my need. We could integrate downshift with TextField for auto complete. Why we cant do the same with Select? I think its common as well for react-select or other libraries.

  2. I tried to mark the MenuProps open to false without children for the Select component, the error I got was children is required.

  3. Do with another approach, I remove select=true and just use TextField with endAdornment with dropdown icon, but extra css is needed to make it like Material Design. And I feel this is a bit hacky.

I will provide an example when I have time to do it.

@oliviertassinari
Copy link
Member

I believe we should close for #13863.

@joshwooding
Copy link
Member

@oliviertassinari I agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: select This is the name of the generic UI component, not the React module! discussion
Projects
None yet
Development

No branches or pull requests

6 participants