Skip to content

Commit 467f49e

Browse files
committed
feat(menu): Add BEM classes
You know the drill. - Updated BEM classes, including root, header, footer - Updated docs BREAKING CHANGE: The default template now has the count element inside the link, not outside.
1 parent 193dba5 commit 467f49e

File tree

6 files changed

+132
-28
lines changed

6 files changed

+132
-28
lines changed

README.md

+65-5
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,12 @@ search.addWidget(
707707
```
708708

709709
```css
710+
.ais-refinement-list {
711+
}
712+
.ais-refinement-list--header {
713+
}
714+
.ais-refinement-list--body {
715+
}
710716
.ais-refinement-list--list {
711717
}
712718
.ais-refinement-list--item {
@@ -719,6 +725,8 @@ search.addWidget(
719725
}
720726
.ais-refinement-list--count {
721727
}
728+
.ais-refinement-list--footer {
729+
}
722730
```
723731

724732
### menu
@@ -735,15 +743,21 @@ search.addWidget(
735743
* @param {String[]} [options.sortBy=['count:desc']] How to sort refinements. Possible values: `count|isRefined|name:asc|desc`
736744
* @param {String} [options.limit=100] How many facets values to retrieve
737745
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
738-
* @param {String|String[]} [options.cssClasses.root] CSS class to be added to the wrapper element
739-
* @param {String|String[]} [options.cssClasses.list] CSS class to be added to the list element
740-
* @param {String|String[]} [options.cssClasses.item] CSS class to be added to each item of the list
746+
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
747+
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
748+
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
749+
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
750+
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
751+
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
752+
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
753+
* @param {String|String[]} [options.cssClasses.link] CSS class to add to each link (when using the default template)
754+
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
741755
* @param {Object} [options.templates] Templates to use for the widget
742756
* @param {String|Function} [options.templates.header=''] Header template
743-
* @param {String|Function} [options.templates.item='<a href="{{href}}">{{name}}</a> {{count}}'] Item template, provided with `name`, `count`, `isRefined`
757+
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
744758
* @param {String|Function} [options.templates.footer=''] Footer template
745759
* @param {Function} [options.transformData] Method to change the object passed to the item template
746-
* @param {boolean} [hideWhenNoResults=true] Hide the container when no results match
760+
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
747761
* @return {Object}
748762
*/
749763
```
@@ -764,6 +778,52 @@ search.addWidget(
764778
);
765779
```
766780

781+
#### Styling
782+
783+
```html
784+
<div class="ais-menu">
785+
<div class="ais-menu--header ais-header">[custom header template]</div>
786+
<div class="ais-menu--body">
787+
<div class="ais-menu--list">
788+
<div class="ais-menu--item">
789+
<a class="ais-menu--link" href="/url">
790+
Your value
791+
<span class="ais-menu--count">42</span>
792+
</a>
793+
</div>
794+
<div class="ais-menu--item ais-menu--item__active">
795+
<a class="ais-menu--link" href="/url">
796+
Your active value
797+
<span class="ais-menu--count">42</span>
798+
</a>
799+
</div>
800+
</div>
801+
</div>
802+
<div class="ais-menu--footer ais-footer">[custom footer template]</div>
803+
</div>
804+
```
805+
806+
```css
807+
.ais-menu {
808+
}
809+
.ais-menu--header {
810+
}
811+
.ais-menu--body {
812+
}
813+
.ais-menu--list {
814+
}
815+
.ais-menu--item {
816+
}
817+
.ais-menu--item__active {
818+
}
819+
.ais-menu--link {
820+
}
821+
.ais-menu--count {
822+
}
823+
.ais-menu--footer {
824+
}
825+
```
826+
767827
### rangeSlider
768828

769829
![Example of the rangeSlider widget][rangeSlider]

example/app.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ search.addWidget(
121121
limit: 10,
122122
cssClasses: {
123123
header: 'panel-heading',
124-
root: 'list-group'
124+
root: 'list-group',
125+
link: 'list-group-item'
125126
},
126127
templates: {
127128
header: 'Categories',

index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ instantsearch.widgets = {
1111
hierarchicalMenu: require('./widgets/hierarchicalMenu'),
1212
hits: require('./widgets/hits/hits'),
1313
indexSelector: require('./widgets/index-selector/index-selector'),
14-
menu: require('./widgets/menu'),
14+
menu: require('./widgets/menu/menu.js'),
1515
refinementList: require('./widgets/refinement-list/refinement-list.js'),
1616
pagination: require('./widgets/pagination/pagination'),
1717
searchBox: require('./widgets/search-box'),

themes/default/default.css

+26
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@
6767
}
6868

6969
/* REFINEMENT LIST */
70+
.ais-refinement-list {
71+
}
72+
.ais-refinement-list--header {
73+
}
74+
.ais-refinement-list--body {
75+
}
7076
.ais-refinement-list--list {
7177
}
7278
.ais-refinement-list--item {
@@ -79,8 +85,28 @@
7985
}
8086
.ais-refinement-list--count {
8187
}
88+
.ais-refinement-list--footer {
89+
}
8290

8391
/* MENU */
92+
.ais-menu {
93+
}
94+
.ais-menu--header {
95+
}
96+
.ais-menu--body {
97+
}
98+
.ais-menu--list {
99+
}
100+
.ais-menu--item {
101+
}
102+
.ais-menu--item__active {
103+
}
104+
.ais-menu--link {
105+
}
106+
.ais-menu--count {
107+
}
108+
.ais-menu--footer {
109+
}
84110

85111
/* TOGGLE */
86112

widgets/menu/defaultTemplates.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
header: '',
3+
item: `<a class="{{cssClasses.link}}" href="{{url}}">{{name}} <span class="{{cssClasses.count}}">{{count}}</span></a>`,
4+
footer: ''
5+
};

widgets/menu.js widgets/menu/menu.js

+33-21
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
var React = require('react');
22
var ReactDOM = require('react-dom');
33

4-
var utils = require('../lib/utils.js');
5-
var autoHide = require('../decorators/autoHide');
6-
var headerFooter = require('../decorators/headerFooter');
7-
var RefinementList = autoHide(headerFooter(require('../components/RefinementList')));
4+
var utils = require('../../lib/utils.js');
5+
var bem = utils.bemHelper('ais-menu');
6+
var cx = require('classnames/dedupe');
7+
var autoHide = require('../../decorators/autoHide');
8+
var headerFooter = require('../../decorators/headerFooter');
9+
var RefinementList = autoHide(headerFooter(require('../../components/RefinementList')));
810

9-
var defaultTemplates = {
10-
header: '',
11-
item: '<a href="{{url}}">{{name}}</a> {{count}}',
12-
footer: ''
13-
};
11+
var defaultTemplates = require('./defaultTemplates.js');
1412

1513
/**
1614
* Create a menu out of a facet
@@ -19,35 +17,37 @@ var defaultTemplates = {
1917
* @param {String[]} [options.sortBy=['count:desc']] How to sort refinements. Possible values: `count|isRefined|name:asc|desc`
2018
* @param {String} [options.limit=100] How many facets values to retrieve
2119
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
22-
* @param {String|String[]} [options.cssClasses.root] CSS class to be added to the wrapper element
23-
* @param {String|String[]} [options.cssClasses.list] CSS class to be added to the list element
24-
* @param {String|String[]} [options.cssClasses.item] CSS class to be added to each item of the list
20+
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
21+
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
22+
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
23+
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
24+
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
25+
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
26+
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
27+
* @param {String|String[]} [options.cssClasses.link] CSS class to add to each link (when using the default template)
28+
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
2529
* @param {Object} [options.templates] Templates to use for the widget
2630
* @param {String|Function} [options.templates.header=''] Header template
27-
* @param {String|Function} [options.templates.item='<a href="{{href}}">{{name}}</a> {{count}}'] Item template, provided with `name`, `count`, `isRefined`
31+
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
2832
* @param {String|Function} [options.templates.footer=''] Footer template
2933
* @param {Function} [options.transformData] Method to change the object passed to the item template
3034
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
3135
* @return {Object}
3236
*/
3337
function menu({
34-
container = null,
35-
facetName = null,
38+
container,
39+
facetName,
3640
sortBy = ['count:desc'],
3741
limit = 100,
38-
cssClasses = {
39-
root: null,
40-
list: null,
41-
item: null
42-
},
42+
cssClasses = {},
4343
templates = defaultTemplates,
4444
transformData,
4545
hideWhenNoResults = true
4646
}) {
4747
var containerNode = utils.getContainerNode(container);
4848
var usage = 'Usage: menu({container, facetName, [sortBy, limit, cssClasses.{root,list,item}, templates.{header,item,footer}, transformData, hideWhenResults]})';
4949

50-
if (container === null || facetName === null) {
50+
if (!container || !facetName) {
5151
throw new Error(usage);
5252
}
5353

@@ -72,6 +72,18 @@ function menu({
7272
templates
7373
});
7474

75+
cssClasses = {
76+
root: cx(bem(null), cssClasses.root),
77+
header: cx(bem('header'), cssClasses.header),
78+
body: cx(bem('body'), cssClasses.body),
79+
footer: cx(bem('footer'), cssClasses.footer),
80+
list: cx(bem('list'), cssClasses.list),
81+
item: cx(bem('item'), cssClasses.item),
82+
active: cx(bem('item', 'active'), cssClasses.active),
83+
link: cx(bem('link'), cssClasses.link),
84+
count: cx(bem('count'), cssClasses.count)
85+
};
86+
7587
ReactDOM.render(
7688
<RefinementList
7789
createURL={(facetValue) => createURL(state.toggleRefinement(hierarchicalFacetName, facetValue))}

0 commit comments

Comments
 (0)