Skip to content

Commit

Permalink
feat(menu): Add BEM classes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pixelastic committed Oct 20, 2015
1 parent 193dba5 commit 467f49e
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 28 deletions.
70 changes: 65 additions & 5 deletions README.md
Expand Up @@ -707,6 +707,12 @@ search.addWidget(
```

```css
.ais-refinement-list {
}
.ais-refinement-list--header {
}
.ais-refinement-list--body {
}
.ais-refinement-list--list {
}
.ais-refinement-list--item {
Expand All @@ -719,6 +725,8 @@ search.addWidget(
}
.ais-refinement-list--count {
}
.ais-refinement-list--footer {
}
```

### menu
Expand All @@ -735,15 +743,21 @@ search.addWidget(
* @param {String[]} [options.sortBy=['count:desc']] How to sort refinements. Possible values: `count|isRefined|name:asc|desc`
* @param {String} [options.limit=100] How many facets values to retrieve
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
* @param {String|String[]} [options.cssClasses.root] CSS class to be added to the wrapper element
* @param {String|String[]} [options.cssClasses.list] CSS class to be added to the list element
* @param {String|String[]} [options.cssClasses.item] CSS class to be added to each item of the list
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
* @param {String|String[]} [options.cssClasses.link] CSS class to add to each link (when using the default template)
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
* @param {Object} [options.templates] Templates to use for the widget
* @param {String|Function} [options.templates.header=''] Header template
* @param {String|Function} [options.templates.item='<a href="{{href}}">{{name}}</a> {{count}}'] Item template, provided with `name`, `count`, `isRefined`
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
* @param {String|Function} [options.templates.footer=''] Footer template
* @param {Function} [options.transformData] Method to change the object passed to the item template
* @param {boolean} [hideWhenNoResults=true] Hide the container when no results match
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
* @return {Object}
*/
```
Expand All @@ -764,6 +778,52 @@ search.addWidget(
);
```

#### Styling

```html
<div class="ais-menu">
<div class="ais-menu--header ais-header">[custom header template]</div>
<div class="ais-menu--body">
<div class="ais-menu--list">
<div class="ais-menu--item">
<a class="ais-menu--link" href="/url">
Your value
<span class="ais-menu--count">42</span>
</a>
</div>
<div class="ais-menu--item ais-menu--item__active">
<a class="ais-menu--link" href="/url">
Your active value
<span class="ais-menu--count">42</span>
</a>
</div>
</div>
</div>
<div class="ais-menu--footer ais-footer">[custom footer template]</div>
</div>
```

```css
.ais-menu {
}
.ais-menu--header {
}
.ais-menu--body {
}
.ais-menu--list {
}
.ais-menu--item {
}
.ais-menu--item__active {
}
.ais-menu--link {
}
.ais-menu--count {
}
.ais-menu--footer {
}
```

### rangeSlider

![Example of the rangeSlider widget][rangeSlider]
Expand Down
3 changes: 2 additions & 1 deletion example/app.js
Expand Up @@ -121,7 +121,8 @@ search.addWidget(
limit: 10,
cssClasses: {
header: 'panel-heading',
root: 'list-group'
root: 'list-group',
link: 'list-group-item'
},
templates: {
header: 'Categories',
Expand Down
2 changes: 1 addition & 1 deletion index.js
Expand Up @@ -11,7 +11,7 @@ instantsearch.widgets = {
hierarchicalMenu: require('./widgets/hierarchicalMenu'),
hits: require('./widgets/hits/hits'),
indexSelector: require('./widgets/index-selector/index-selector'),
menu: require('./widgets/menu'),
menu: require('./widgets/menu/menu.js'),
refinementList: require('./widgets/refinement-list/refinement-list.js'),
pagination: require('./widgets/pagination/pagination'),
searchBox: require('./widgets/search-box'),
Expand Down
26 changes: 26 additions & 0 deletions themes/default/default.css
Expand Up @@ -67,6 +67,12 @@
}

/* REFINEMENT LIST */
.ais-refinement-list {
}
.ais-refinement-list--header {
}
.ais-refinement-list--body {
}
.ais-refinement-list--list {
}
.ais-refinement-list--item {
Expand All @@ -79,8 +85,28 @@
}
.ais-refinement-list--count {
}
.ais-refinement-list--footer {
}

/* MENU */
.ais-menu {
}
.ais-menu--header {
}
.ais-menu--body {
}
.ais-menu--list {
}
.ais-menu--item {
}
.ais-menu--item__active {
}
.ais-menu--link {
}
.ais-menu--count {
}
.ais-menu--footer {
}

/* TOGGLE */

Expand Down
5 changes: 5 additions & 0 deletions widgets/menu/defaultTemplates.js
@@ -0,0 +1,5 @@
module.exports = {
header: '',
item: `<a class="{{cssClasses.link}}" href="{{url}}">{{name}} <span class="{{cssClasses.count}}">{{count}}</span></a>`,
footer: ''
};
54 changes: 33 additions & 21 deletions widgets/menu.js → widgets/menu/menu.js
@@ -1,16 +1,14 @@
var React = require('react');
var ReactDOM = require('react-dom');

var utils = require('../lib/utils.js');
var autoHide = require('../decorators/autoHide');
var headerFooter = require('../decorators/headerFooter');
var RefinementList = autoHide(headerFooter(require('../components/RefinementList')));
var utils = require('../../lib/utils.js');
var bem = utils.bemHelper('ais-menu');
var cx = require('classnames/dedupe');
var autoHide = require('../../decorators/autoHide');
var headerFooter = require('../../decorators/headerFooter');
var RefinementList = autoHide(headerFooter(require('../../components/RefinementList')));

var defaultTemplates = {
header: '',
item: '<a href="{{url}}">{{name}}</a> {{count}}',
footer: ''
};
var defaultTemplates = require('./defaultTemplates.js');

/**
* Create a menu out of a facet
Expand All @@ -19,35 +17,37 @@ var defaultTemplates = {
* @param {String[]} [options.sortBy=['count:desc']] How to sort refinements. Possible values: `count|isRefined|name:asc|desc`
* @param {String} [options.limit=100] How many facets values to retrieve
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
* @param {String|String[]} [options.cssClasses.root] CSS class to be added to the wrapper element
* @param {String|String[]} [options.cssClasses.list] CSS class to be added to the list element
* @param {String|String[]} [options.cssClasses.item] CSS class to be added to each item of the list
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
* @param {String|String[]} [options.cssClasses.link] CSS class to add to each link (when using the default template)
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
* @param {Object} [options.templates] Templates to use for the widget
* @param {String|Function} [options.templates.header=''] Header template
* @param {String|Function} [options.templates.item='<a href="{{href}}">{{name}}</a> {{count}}'] Item template, provided with `name`, `count`, `isRefined`
* @param {String|Function} [options.templates.item] Item template, provided with `name`, `count`, `isRefined`
* @param {String|Function} [options.templates.footer=''] Footer template
* @param {Function} [options.transformData] Method to change the object passed to the item template
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
* @return {Object}
*/
function menu({
container = null,
facetName = null,
container,
facetName,
sortBy = ['count:desc'],
limit = 100,
cssClasses = {
root: null,
list: null,
item: null
},
cssClasses = {},
templates = defaultTemplates,
transformData,
hideWhenNoResults = true
}) {
var containerNode = utils.getContainerNode(container);
var usage = 'Usage: menu({container, facetName, [sortBy, limit, cssClasses.{root,list,item}, templates.{header,item,footer}, transformData, hideWhenResults]})';

if (container === null || facetName === null) {
if (!container || !facetName) {
throw new Error(usage);
}

Expand All @@ -72,6 +72,18 @@ function menu({
templates
});

cssClasses = {
root: cx(bem(null), cssClasses.root),
header: cx(bem('header'), cssClasses.header),
body: cx(bem('body'), cssClasses.body),
footer: cx(bem('footer'), cssClasses.footer),
list: cx(bem('list'), cssClasses.list),
item: cx(bem('item'), cssClasses.item),
active: cx(bem('item', 'active'), cssClasses.active),
link: cx(bem('link'), cssClasses.link),
count: cx(bem('count'), cssClasses.count)
};

ReactDOM.render(
<RefinementList
createURL={(facetValue) => createURL(state.toggleRefinement(hierarchicalFacetName, facetValue))}
Expand Down

0 comments on commit 467f49e

Please sign in to comment.