Skip to content

Commit 393b66d

Browse files
authored
Merge pull request #5 from cburbank/custom-styles
feat(styles): Add styles prop to allow for custom inline styles
2 parents a609388 + 96a107b commit 393b66d

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,35 @@ render() {
155155
```
156156
Now you can easily apply custom CSS styles using the classNames!
157157

158+
#### styles
159+
Type `Object`,
160+
Required: `false`
161+
162+
You can provide custom inline styles to elements.
163+
Accepted keys are `root`, `label`, `input`, `autocompleteContainer`, `autocompleteItem`, `autocompleteItemActive`
164+
165+
```js
166+
// custom style examples
167+
render() {
168+
const myStyles = {
169+
root: { position: 'absolute' },
170+
label: { color: 'red' },
171+
input: { width: '100%' },
172+
autocompleteContainer: { backgroundColor: 'green' },
173+
autocompleteItem: { color: 'black' },
174+
autocompleteItemActive: { color: 'blue' }
175+
}
176+
177+
return (
178+
<PlacesAutocomplete
179+
value={this.state.address}
180+
onChange={this.onChange}
181+
styles={myStyles}
182+
/>
183+
)
184+
}
185+
```
186+
158187
#### placeholder
159188
Type: `String`,
160189
Required: `false`,

src/PlacesAutocomplete.js

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react'
22

33
const defaultStyles = {
4-
autocompleteContainer: {
4+
root: {
55
position: 'relative',
66
paddingBottom: '0px',
77
},
@@ -13,7 +13,7 @@ const defaultStyles = {
1313
left: 0,
1414
zIndex: 9998,
1515
},
16-
autocompleteWrapper: {
16+
autocompleteContainer: {
1717
position: 'absolute',
1818
top: '100%',
1919
backgroundColor: 'white',
@@ -22,9 +22,13 @@ const defaultStyles = {
2222
zIndex: 9999,
2323
},
2424
autocompleteItem: {
25+
backgroundColor: '#ffffff',
2526
padding: '10px',
2627
color: '#555',
2728
cursor: 'pointer',
29+
},
30+
autocompleteItemActive: {
31+
backgroundColor: '#fafafa'
2832
}
2933
}
3034

@@ -152,18 +156,17 @@ class PlacesAutocomplete extends React.Component {
152156
this.autocompleteService.getPlacePredictions({ input: event.target.value }, this.autocompleteCallback)
153157
}
154158

155-
// TODO: this should be customizable.
156159
autocompleteItemStyle(active) {
157160
if (active) {
158-
return { backgroundColor: '#fafafa' }
161+
return { ...defaultStyles.autocompleteItemActive, ...this.props.styles.autocompleteItemActive }
159162
} else {
160-
return { backgroundColor: '#ffffff' }
163+
return {}
161164
}
162165
}
163166

164167
renderLabel() {
165168
if (this.props.hideLabel) { return null }
166-
return (<label className={this.props.classNames.label || ''}>Location</label>)
169+
return (<label style={this.props.styles.label} className={this.props.classNames.label || ''}>Location</label>)
167170
}
168171

169172
renderOverlay() {
@@ -179,18 +182,19 @@ class PlacesAutocomplete extends React.Component {
179182

180183
renderAutocomplete() {
181184
const { autocompleteItems } = this.state
185+
const { styles } = this.props
182186
if (autocompleteItems.length === 0) { return null }
183187
return (
184188
<div
185189
id="PlacesAutocomplete__autocomplete-container"
186190
className={this.props.classNames.autocompleteContainer || ''}
187-
style={defaultStyles.autocompleteWrapper}>
191+
style={{ ...defaultStyles.autocompleteContainer, ...styles.autocompleteContainer }}>
188192
{autocompleteItems.map((p, idx) => (
189193
<div
190194
key={p.placeId}
191195
onMouseOver={() => this._setActiveItemAtIndex(p.index)}
192196
onClick={() => this.selectAddress(p.suggestion)}
193-
style={{ ...this.autocompleteItemStyle(p.active), ...defaultStyles.autocompleteItem }}>
197+
style={{ ...defaultStyles.autocompleteItem, ...styles.autocompleteItem, ...this.autocompleteItemStyle(p.active) }}>
194198
{this.props.autocompleteItem({ suggestion: p.suggestion })}
195199
</div>
196200
))}
@@ -200,10 +204,10 @@ class PlacesAutocomplete extends React.Component {
200204

201205
// TODO: remove `classNames.container` in the next version release.
202206
render() {
203-
const { classNames, placeholder, value } = this.props
207+
const { classNames, placeholder, styles, value } = this.props
204208
return (
205209
<div
206-
style={defaultStyles.autocompleteContainer}
210+
style={{ ...defaultStyles.root, ...styles.root }}
207211
className={classNames.root || classNames.container || ''}
208212
>
209213
{this.renderLabel()}
@@ -214,6 +218,7 @@ class PlacesAutocomplete extends React.Component {
214218
value={value}
215219
onChange={this.handleInputChange}
216220
onKeyDown={this.handleInputKeyDown}
221+
style={styles.input}
217222
/>
218223
{this.renderOverlay()}
219224
{this.renderAutocomplete()}
@@ -235,13 +240,22 @@ PlacesAutocomplete.propTypes = {
235240
input: React.PropTypes.string,
236241
autocompleteContainer: React.PropTypes.string,
237242
}),
243+
styles: React.PropTypes.shape({
244+
root: React.PropTypes.object,
245+
label: React.PropTypes.object,
246+
input: React.PropTypes.object,
247+
autocompleteContainer: React.PropTypes.object,
248+
autocompleteItem: React.PropTypes.object,
249+
autocompleteItemActive: React.PropTypes.object
250+
})
238251
};
239252

240253
PlacesAutocomplete.defaultProps = {
241254
placeholder: 'Address',
242255
hideLabel: false,
243256
classNames: {},
244-
autocompleteItem: ({ suggestion }) => (<div>{suggestion}</div>)
257+
autocompleteItem: ({ suggestion }) => (<div>{suggestion}</div>),
258+
styles: {}
245259
}
246260

247261
export default PlacesAutocomplete

src/tests/index.spec.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,56 @@ describe('customizable autocompleteItem', () => {
132132
})
133133
})
134134

135+
describe('custom inline styles', () => {
136+
let wrapper;
137+
beforeEach(() => {
138+
const styles = {
139+
root: { position: 'absolute' },
140+
label: { color: 'red' },
141+
input: { width: '100%' },
142+
autocompleteContainer: { backgroundColor: 'green' },
143+
autocompleteItem: { color: 'black' },
144+
autocompleteItemActive: { color: 'blue' }
145+
}
146+
const classNames = {
147+
root: 'root-element',
148+
label: 'label-element',
149+
input: 'input-element',
150+
autocompleteContainer: 'autocomplete-container'
151+
}
152+
wrapper = shallow(<PlacesAutocomplete styles={styles} classNames={classNames} value="LA" onChange={() => {}}/>)
153+
})
154+
155+
it('lets you set custom styles for the root element', () => {
156+
expect(wrapper.find('.root-element').props().style.position).to.equal('absolute')
157+
})
158+
159+
it('lets you set custom styles for the label element', () => {
160+
expect(wrapper.find('.label-element').props().style.color).to.equal('red')
161+
})
162+
163+
it('lets you set custom styles for the input element', () => {
164+
expect(wrapper.find('.input-element').props().style.width).to.equal('100%')
165+
})
166+
167+
it('lets you set custom styles for the autocomplete container element', () => {
168+
wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] })
169+
expect(wrapper.find('.autocomplete-container').props().style.backgroundColor).to.equal('green')
170+
})
171+
172+
it('lets you set custom styles for autocomplete items', () => {
173+
wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: false, index: 0 }] })
174+
const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0)
175+
expect(item.props().style.color).to.equal('black')
176+
})
177+
178+
it('lets you set custom styles for active autocomplete items', () => {
179+
wrapper.setState({ autocompleteItems: [{ suggestion: 'San Francisco, CA', placeId: 1, active: true, index: 0 }] })
180+
const item = wrapper.find("#PlacesAutocomplete__autocomplete-container").childAt(0)
181+
expect(item.props().style.color).to.equal('blue')
182+
})
183+
184+
})
135185

136186
// TODO: test geocodeByAddress function
137187
describe('geocodeByAddress', () => {

0 commit comments

Comments
 (0)