Skip to content

Commit b09b830

Browse files
committed
feat(refinement-list): Add BEM naming
1 parent 40a359b commit b09b830

File tree

8 files changed

+111
-27
lines changed

8 files changed

+111
-27
lines changed

README.md

+44-5
Original file line numberDiff line numberDiff line change
@@ -556,14 +556,19 @@ search.addWidget(
556556
* @param {String} [options.limit=1000] How much facet values to get
557557
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
558558
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
559+
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
560+
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
561+
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
559562
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
560563
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
564+
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
565+
* @param {String|String[]} [options.cssClasses.label] CSS class to add to each label element (when using the default template)
566+
* @param {String|String[]} [options.cssClasses.checkbox] CSS class to add to each checkbox element (when using the default template)
567+
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
561568
* @param {Object} [options.templates] Templates to use for the widget
562-
* @param {String|Function} [options.templates.header=''] Header template
563-
* @param {String|Function} [options.templates.item=`<label>
564-
<input type="checkbox" value="{{name}}" {{#isRefined}}checked{{/isRefined}} />{{name}} <span>{{count}}</span>
565-
</label>`] Item template, provided with `name`, `count`, `isRefined`
566-
* @param {String|Function} [options.templates.footer=''] Footer template
569+
* @param {String|Function} [options.templates.header] Header template
570+
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
571+
* @param {String|Function} [options.templates.footer] Footer template
567572
* @param {Function} [options.transformData] Function to change the object passed to the item template
568573
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
569574
* @return {Object}
@@ -585,6 +590,40 @@ search.addWidget(
585590
);
586591
```
587592

593+
#### Styling
594+
595+
```html
596+
<div class="ais-refinement-list--list">
597+
<div class="ais-refinement-list--item">
598+
<label class="ais-refinement-list--label">
599+
<input type="checkbox" class="ais-refinement-list--checkbox" value="your_value"> Your value
600+
<span class="ais-refinement-list--count">42</span>
601+
</label>
602+
</div>
603+
<div class="ais-refinement-list--item ais-refinement-list--item__active">
604+
<label class="ais-refinement-list--label">
605+
<input type="checkbox" class="ais-refinement-list--checkbox" value="your_selected_value" checked="checked"> Your selected value
606+
<span class="ais-refinement-list--count">42</span>
607+
</label>
608+
</div>
609+
</div>
610+
```
611+
612+
```css
613+
.ais-refinement-list--list {
614+
}
615+
.ais-refinement-list--item {
616+
}
617+
.ais-refinement-list--item__active {
618+
}
619+
.ais-refinement-list--label {
620+
}
621+
.ais-refinement-list--checkbox {
622+
}
623+
.ais-refinement-list--count {
624+
}
625+
```
626+
588627
### menu
589628

590629
![Example of the menu widget][menu]

components/RefinementList.js

+9-6
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,19 @@ class RefinementList extends React.Component {
1616
<RefinementList {...this.props} facetValues={facetValue.data} /> :
1717
null;
1818

19+
var templateData = {...facetValue, cssClasses: this.props.cssClasses};
20+
21+
var cssClassItem = cx(this.props.cssClasses.item, {
22+
[this.props.cssClasses.active]: facetValue.isRefined
23+
});
24+
1925
return (
2026
<div
21-
className={cx(this.props.cssClasses.item)}
27+
className={cssClassItem}
2228
key={facetValue[this.props.facetNameKey]}
2329
onClick={this.handleClick.bind(this, facetValue[this.props.facetNameKey])}
2430
>
25-
<Template data={facetValue} templateKey="item" {...this.props.templateProps} />
31+
<Template data={templateData} templateKey="item" {...this.props.templateProps} />
2632
{subList}
2733
</div>
2834
);
@@ -96,10 +102,7 @@ RefinementList.propTypes = {
96102
};
97103

98104
RefinementList.defaultProps = {
99-
cssClasses: {
100-
item: null,
101-
list: null
102-
},
105+
cssClasses: {},
103106
facetNameKey: 'name'
104107
};
105108

example/app.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ search.addWidget(
7070
operator: 'or',
7171
limit: 10,
7272
cssClasses: {
73-
list: 'nav nav-stacked panel-body'
73+
list: 'nav nav-stacked panel-body',
74+
item: 'checkbox',
75+
count: 'badge pull-right'
7476
},
7577
templates: {
76-
header: '<div class="panel-heading">Brands</div>',
77-
item: require('./templates/or.html')
78+
header: '<div class="panel-heading">Brands</div>'
7879
}
7980
})
8081
);

example/style.css

+4
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,7 @@ body {
7575
.hierarchical-categories-list .hierarchical-categories-list {
7676
padding-left: 20px;
7777
}
78+
79+
.ais-refinement-list--label {
80+
display: block;
81+
}

themes/debug.css

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
position:relative;
99
}
1010
[class^=ais-]:hover:after {
11-
background:red;
12-
background: grey;
11+
background: red;
1312
color: black;
1413
content:attr(class);
1514
font-size:1rem;
@@ -20,6 +19,7 @@
2019
top:0;
2120
white-space: nowrap;
2221
z-index:10;
22+
font-weight: normal;
2323
}
2424
[class^=ais-] [class^=ais-] {
2525
outline: 1px solid orange !important;
@@ -39,3 +39,12 @@
3939
top:40px;
4040
z-index:1000;
4141
}
42+
[class^=ais-] [class^=ais-] [class^=ais-] [class^=ais-] {
43+
outline: 1px solid cyan !important;
44+
position:relative;
45+
}
46+
[class^=ais-] [class^=ais-] [class^=ais-] [class^=ais-]:hover:after {
47+
background: cyan;
48+
top:40px;
49+
z-index:1100;
50+
}
+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
module.exports = {
22
header: '',
3-
item: `<label>
4-
<input type="checkbox" value="{{name}}" {{#isRefined}}checked{{/isRefined}} />{{name}}
5-
<span>{{count}}</span>
3+
item: `<label class="{{cssClasses.label}}">
4+
<input type="checkbox" class="{{cssClasses.checkbox}}" value="{{name}}" {{#isRefined}}checked{{/isRefined}} />{{name}}
5+
<span class="{{cssClasses.count}}">{{count}}</span>
66
</label>`,
77
footer: ''
88
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.ais-refinement-list--list {
2+
}
3+
.ais-refinement-list--item {
4+
}
5+
.ais-refinement-list--item__active {
6+
}
7+
.ais-refinement-list--label {
8+
}
9+
.ais-refinement-list--checkbox {
10+
}
11+
.ais-refinement-list--count {
12+
}

widgets/refinement-list/refinement-list.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ var React = require('react');
22
var ReactDOM = require('react-dom');
33

44
var utils = require('../../lib/utils.js');
5+
var bem = utils.bemHelper('ais-refinement-list');
6+
var cx = require('classnames/dedupe');
57

68
var autoHide = require('../../decorators/autoHide');
79
var headerFooter = require('../../decorators/headerFooter');
@@ -18,14 +20,19 @@ var defaultTemplates = require('./defaultTemplates');
1820
* @param {String} [options.limit=1000] How much facet values to get
1921
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
2022
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
23+
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
24+
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
25+
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
2126
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
2227
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
28+
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
29+
* @param {String|String[]} [options.cssClasses.label] CSS class to add to each label element (when using the default template)
30+
* @param {String|String[]} [options.cssClasses.checkbox] CSS class to add to each checkbox element (when using the default template)
31+
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
2332
* @param {Object} [options.templates] Templates to use for the widget
24-
* @param {String|Function} [options.templates.header=''] Header template
25-
* @param {String|Function} [options.templates.item=`<label>
26-
<input type="checkbox" value="{{name}}" {{#isRefined}}checked{{/isRefined}} />{{name}} <span>{{count}}</span>
27-
</label>`] Item template, provided with `name`, `count`, `isRefined`
28-
* @param {String|Function} [options.templates.footer=''] Footer template
33+
* @param {String|Function} [options.templates.header] Header template
34+
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
35+
* @param {String|Function} [options.templates.footer] Footer template
2936
* @param {Function} [options.transformData] Function to change the object passed to the item template
3037
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
3138
* @return {Object}
@@ -37,12 +44,12 @@ function refinementList({
3744
sortBy = ['count:desc'],
3845
limit = 1000,
3946
cssClasses = {},
40-
hideWhenNoResults = true,
4147
templates = defaultTemplates,
42-
transformData
48+
transformData,
49+
hideWhenNoResults = true
4350
}) {
4451
var containerNode = utils.getContainerNode(container);
45-
var usage = 'Usage: refinementList({container, facetName, [operator, sortBy, limit, cssClasses.{root,list,item}, templates.{header,item,footer}, transformData, hideIfNoResults]})';
52+
var usage = 'Usage: refinementList({container, facetName, [operator, sortBy, limit, cssClasses.{root,header,body,footer,list,item,active,label,checkbox,count}, templates.{header,item,footer}, transformData, hideIfNoResults]})';
4653

4754
if (!container || !facetName) {
4855
throw new Error(usage);
@@ -79,6 +86,15 @@ function refinementList({
7986

8087
var facetValues = results.getFacetValues(facetName, {sortBy: sortBy}).slice(0, limit);
8188

89+
cssClasses = {
90+
list: cx(bem('list'), cssClasses.list),
91+
item: cx(bem('item'), cssClasses.item),
92+
active: cx(bem('item', 'active'), cssClasses.active),
93+
label: cx(bem('label'), cssClasses.label),
94+
checkbox: cx(bem('checkbox'), cssClasses.checkbox),
95+
count: cx(bem('count'), cssClasses.count)
96+
};
97+
8298
ReactDOM.render(
8399
<RefinementList
84100
cssClasses={cssClasses}

0 commit comments

Comments
 (0)