JedWatson / react-select

The Select Component for React.js
https://react-select.com/
MIT License
27.62k stars 4.12k forks source link

Custom control doesnot work #4125

Closed kamarajuPrathi closed 2 years ago

kamarajuPrathi commented 4 years ago

i am using @rmrc/textfield(https://www.npmjs.com/package/@rmwc/textfield)

to provide that as a custom control , i am not sure what props do i need to pass to behave it as select ..

kamarajuPrathi commented 4 years ago

i tried multiple ways but it doesnt work , do you have a sandbox or live example

kamarajuPrathi commented 4 years ago

@ebonow can you let me know how to do changes for it

ebonow commented 4 years ago

Using this as a reference, I am not sure how to use this as a custom component in react-select. I think the better route might be to take on the styling to be similar.

Here is some code taken from my usage. I wrote a custom component for ValueContainer.

const ValueContainer = ({ children, ...props }) => {
  const { icon, error, inputId, label, isSearchable } = props.selectProps;
  const classNames = {
    icon: 'react-select__icon',
    label: 'react-select__label',
    value: CN('react-select__value', { 'react-select__value--no-label': !label }),
    valueContainer: CN({ 'react-select__value-container--not-searchable': !isSearchable }),
  };

  return (
    <components.ValueContainer {...props} className={classNames.valueContainer}>
      {(!!icon) && (error
        ? <ErrorIcon />
        : <Icon className={classNames.icon} name={icon} />
      )}
      <div className={classNames.value}>
        { children }
        { !!label && <label htmlFor={inputId} className={classNames.label}>{label}</label> }
      </div>
    </components.ValueContainer>
  );

You can ignore the Icon stuff or use something similar if it works for you use-case.

Using this I pass in a label prop to the Select. As you can see, any props unused by react-select are still available to your innerComponents.

Here is some of my CSS to get the floating label animated:

.react-select__label {
  position: absolute;
  font-size: 14px;
  top: 50%;
  transform: translateY(-50%);
  left: 3px;
  white-space: nowrap;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: all 300ms;

  .react-select__control--is-focused &,
  .react-select__value-container--has-value & {
    top: 20%;
    font-size: 10px;
    font-weight: bold;
  }
}

There are ways this can be done otherwise such as using emotion to overwrite classNames and styles, but this was my shot at a similar UX approach for the floating label.

Regarding the 3 styles, Standard, Filled, Outlined: You could also pass in other props to the Select to determine what kind of styling you want and apply it to the styling for the Control since that is what has the borders and detects focus.

That would allow you to modify the borders, border-radius, and animated underline components.

Let me know if you have any questions about any of this or how to move forward.

kamarajuPrathi commented 4 years ago

thank you @ebonow i will give a try , i was looking at replacing the complete control with Text field ..

ebonow commented 4 years ago

@kamarajuPrathi It might be possible. If you create a CodeSandbox, I can can try to play with the custom components this week. My immediate thoughts are it might be possible by trying the following:

const styles = { control: () => ({}) }
const Input = ({ innerRef, innerProps }) => {
  const { label, variant='outlined' } = innerProps.selectProps;
  return <TextField ref={innerRef} label={label} variant={variant} />
}

return (
  <Select 
    label={label}
    variant={variant}

    styles={styles} 
    components={{ Input }}
    controlShouldRender={false}
  />

This doesn't solve how to properly display with indicators, and I am not entirely sure that the innerRef will work with the TextField as I am not sure how it exposes the input component, but hopefully this is a start.

kamarajuPrathi commented 4 years ago

@ebonow sure i will post a codesandbox

kamarajuPrathi commented 4 years ago

@ebonow please find this code link https://codesandbox.io/s/react-select-custom-component-lkgv6 here the texfield in @material-ui/core .. i am looking for TextField from @rmwc

ebonow commented 4 years ago

Ok, I referenced the Material UI page because I am not familiar with this particular library from rmwc and the git page didn't really have any demos to look at. After a bit more looking I did find this: https://rmwc.io/text-fields

I appreciate the CodeSandbox. I've already forked it and will try to work through more of it this week to see how to improve performance (already checked out commented link to issue).

moumnimohamed commented 4 years ago

import React, { Component } from "react"; import Select from "react-select";

const options = [ { value: "chocolate", label: "Chocolate" }, { value: "strawberry", label: "Strawberry" }, { value: "vanilla", label: "Vanilla" }, ];

const customStyles = { menu: (provided, state) => ({ ...provided, width: state.selectProps.width, borderBottom: "1px dotted pink", color: state.selectProps.menuColor, padding: 20, }),

control: ( _, { selectProps: { height, width, border, justifyContent, display ,borderRadius,boxShadow} } ) => ({ borderRadius:borderRadius, boxShadow:boxShadow, display: display, height: height, justifyContent: justifyContent, width: width, border: border, }),

/* singleValue: (provided, state) => { const opacity = state.isDisabled ? 0.5 : 1; const transition = 'opacity 300ms';

return { ...provided, opacity, transition };

} */ };

const TravelersSelect = () => ( <Select height="56px" width="100%" display="flex" alignItems="center" menuColor="red" borderRadius="4px" boxShadow="0 2px 3px 0 rgba(123, 131, 142, 0.1)" border="1px solid #e5e7ef" styles={customStyles} isMulti options={options} /> );

export default TravelersSelect;