Search code examples
reactjsreact-selectaphrodite

Style react-select with aphrodite


I'm trying to use some existing styles built in aphrodite to style a 3rd party component react-select. The component has some props on it that allow you to pass a className that defines the class to use for the main container of the component. It then has a classNamePrefix prop that is used to prefix the child items in the component. The documentation details what combination of classNamePrefix + name to use in your style sheet to style each item.

https://react-select.com/styles#using-classnames

I'm looking for an example of how I'd do this using aphrodite. The issue I'm having is when I call css(), I get a random class name. I can't figure out a way to specify the classNamePrefix.


Solution

  • I ended up using the React Select Component API Here is a sample of how I used Aphrodite to inject custom styles in to individual sections of the React Select component.

    // Node Modules
    import { css } from 'aphrodite';
    import PropTypes from 'prop-types';
    import React, { Fragment } from 'react';
    import ReactSelect, { components } from 'react-select';
    // Styles
    import styles from './SelectStyles';
    import { fontStyles } from 'styles';
    // Assets
    import caretImg from 'images/downCaret.svg';
    
    class Select extends React.Component {
      render() {
        const { noOptionsMessage, onChange, options, value } = this.props;
    
        const Control = props => (
          <components.Control {...props} className={css(styles.selectControl)} />
        );
    
        const DropdownIndicator = props => {
          return (
            components.DropdownIndicator && (
              <components.DropdownIndicator {...props}>
                <img src={caretImg} height="6px" alt="▼" className={css(styles.caret)} />
              </components.DropdownIndicator>
            )
          );
        };
    
        const IndicatorSeparator = ({ innerProps }) => {
          return <span className={css(styles.indicatorSeparator)} {...innerProps} />;
        };
    
        const Menu = props => {
          return (
            <Fragment>
              <components.Menu {...props} className={css(styles.menu)}>
                {props.children}
              </components.Menu>
            </Fragment>
          );
        };
    
        const Option = props => (
          <components.Option
            {...props}
            className={css(
              fontStyles.regular,
              props.isSelected ? styles.menuOptionSelected : styles.menuOption,
            )}
          />
        );
    
        const ValueContainer = ({ children, ...props }) => (
          <components.ValueContainer {...props}>{children}</components.ValueContainer>
        );
    
        return (
          <ReactSelect
            className={css(fontStyles.semibold, styles.selectContainer)}
            components={{
              Control,
              DropdownIndicator,
              IndicatorSeparator,
              Menu,
              Option,
              ValueContainer,
            }}
            isSearchable={true}
            noOptionsMessage={() => noOptionsMessage}
            onChange={onChange}
            options={options}
            value={value}
          />
        );
      }
    }
    
    Select.propTypes = {
      noOptionsMessage: PropTypes.string,
      onChange: PropTypes.func.isRequired,
      options: PropTypes.arrayOf(PropTypes.object),
      value: PropTypes.object,
    };
    
    export default Select;