cedricdelpoux / react-google-places-suggest

React component to select geolocated suggestion from Google Maps Places API
https://cedricdelpoux.github.io/react-google-places-suggest/
MIT License
86 stars 44 forks source link

Stylability #30

Open karlvr opened 6 years ago

karlvr commented 6 years ago

Thank you for this module. We'd like to be able to apply more styles to it using CSS, but it hasn't proven possible due to the way that styles are applied in this project.

I've made a fork that uses css classes instead of the current styling mechanism, and adds class names to every element. This makes it very easy to style.

https://github.com/karlvr/react-google-places-suggest

This removes the use of the styled-components dependency. I have put the default styles into a sample.css file. I figure that users can take what they'd like from those styles. I thought about trying to include it in the component build; couldn't work out how to; and it would make it a bit more work to override the existing styles.

This is obviously quite a change, so I'm not sure that you'd like to merge this. Perhaps you can think of a way to retain the existing behaviour, while supporting a className-based styling model. Whatever happens, I'm interested in your thoughts on this!

Best, Karl

cedricdelpoux commented 6 years ago

Hi @karlvr, thank your help.

The solution will be to expose some primitive with the basic behavior and let the user style components inside a renderProp:

import ReactGooglePlacesSuggest, {
  // To customize style
  List,
  ListItem,
  Prediction,
  // To use a default style
  // ListWrapper
  // ListItemWrapper
  // PredictionWrapper,
} from "react-interactive-component"

import styled from "styled-components"

const Wrapper = styled.div`
  width: 100%;
  position: relative;
`

export default class GoogleSuggest extends React.Component {
  state = {
    search: "",
    value: "",
  }

  handleInputChange = e => {
    this.setState({search: e.target.value, value: e.target.value})
  }

  handleSelectSuggest = (geocodedPrediction, originalPrediction) => {
    console.log(geocodedPrediction, originalPrediction) // eslint-disable-line
    this.setState({search: "", value: geocodedPrediction.formatted_address})
  }

  render() {
    const {search, value} = this.state
    return (
      <ReactGooglePlacesSuggest
        googleMaps={googleMaps}
        onSelectSuggest={this.handleSelectSuggest}
        autocompletionRequest={{
          input: search,
        }}
      >
        {({predictions}) => (
          <Wrapper>
            <input
              type="text"
              value={value}
              placeholder="Search a location"
              onChange={this.handleInputChange}
            />
            {predictions && (
              <List>
                {predictions.map(prediction => <ListItem {...prediction} />)}
              </List>
            )}
          </Wrapper>
        )}
      </ReactGooglePlacesSuggest>
    )
  }
}

I wrote this example quickly without testing anything. There is some work to do to make it functional, but if you understand the idea, it is nice!

I would be very glad if you help me upgrade this library to let user styling each component on his own. Of course it will be a lot of breaking change so it will be a new version

karlvr commented 6 years ago

Thanks for your quick reply! I quite liked the idea of using css classes, but that may be because we are using external CSS (less actually) files for our styling.

What you've suggested above looks like it lets the developer replace the entire set of markup for the component, is that correct? Maybe that's more work than people want to do out of the box.

Perhaps we could a styling configuration object instead, that would let you pass in classNames to use for each element, and doing so would turn off the default styles? Or simply a className prefix, and then we apply default suffixes to each element, and turn off the default styles. Or provide an option in the styling configuration object to keep or turn off default styles:

e.g.

<ReactGooglePlaceSuggest
styleConfig={{
    classNamePrefix: 'react-google-places-suggest-',
    defaultStyles: false,
}}
...
/>
cedricdelpoux commented 6 years ago

Sorry I don't want to accord a privilege about one styling solution on an other. A lot of people use CSS-in-JS solution right now and can't handle css files in their stack.

For a major breaking change, I would like to let people choose to style the widget on their own with the solution they choose and do not force them to use css

karlvr commented 6 years ago

Fair enough, what if such a configuration option could contain class names or style text like you're using with the styledcomponents?

cedricdelpoux commented 6 years ago

I just remember there is a customContainerRender prop you can use to style the list as you want. Did you try using it?

vdmkotai commented 5 years ago

@xuopled customContainerRender just replaces default list wrapper, so onSelectSuggest will not work. Item focus also breaks. It would be very nice if it were possible to modify the styles of the default list wrapper.

cedricdelpoux commented 5 years ago

You are right. Unfortunately I don't have so much time for now to work on this lib but I'm open to Pull Requests :)