Skip to content

Commit 8730c97

Browse files
committed
feat(toggle): Adding BEM class naming
Business as usual. Adding BEM classes to the toggle widget (using refinementList internally)
1 parent 193dba5 commit 8730c97

File tree

7 files changed

+121
-23
lines changed

7 files changed

+121
-23
lines changed

Diff for: README.md

+51-5
Original file line numberDiff line numberDiff line change
@@ -596,15 +596,20 @@ Note that we are not toggling from `true` to `false` here, but from `true` to
596596
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
597597
* @param {String} options.facetName Name of the attribute for faceting (eg. "free_shipping")
598598
* @param {String} options.label Human-readable name of the filter (eg. "Free Shipping")
599-
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
599+
* @param {Object} [options.cssClasses] CSS classes to add
600600
* @param {String|String[]} [options.cssClasses.root] CSS class to add to the root element
601+
* @param {String|String[]} [options.cssClasses.header] CSS class to add to the header element
602+
* @param {String|String[]} [options.cssClasses.body] CSS class to add to the body element
603+
* @param {String|String[]} [options.cssClasses.footer] CSS class to add to the footer element
601604
* @param {String|String[]} [options.cssClasses.list] CSS class to add to the list element
602-
* @param {String|String[]} [options.cssClasses.item] CSS class to add to the item element
605+
* @param {String|String[]} [options.cssClasses.item] CSS class to add to each item element
606+
* @param {String|String[]} [options.cssClasses.active] CSS class to add to each active element
607+
* @param {String|String[]} [options.cssClasses.label] CSS class to add to each label element (when using the default template)
608+
* @param {String|String[]} [options.cssClasses.checkbox] CSS class to add to each checkbox element (when using the default template)
609+
* @param {String|String[]} [options.cssClasses.count] CSS class to add to each count element (when using the default template)
603610
* @param {Object} [options.templates] Templates to use for the widget
604611
* @param {String|Function} [options.templates.header=''] Header template
605-
* @param {String|Function} [options.templates.item='<label>
606-
<input type="checkbox" {{#isRefined}}checked{{/isRefined}} />{{name}} <span>{{count}}</span>
607-
</label>'] Item template
612+
* @param {String|Function} [options.templates.item] Item template
608613
* @param {String|Function} [options.templates.footer=''] Footer template
609614
* @param {Function} [options.transformData] Function to change the object passed to the item template
610615
* @param {boolean} [hideWhenNoResults=true] Hide the container when there's no results
@@ -631,6 +636,47 @@ search.addWidget(
631636
);
632637
```
633638

639+
#### Styling
640+
641+
```html
642+
<div class="ais-toggle">
643+
<div class="ais-toggle--header ais-header">[custom header template]</div>
644+
<div class="ais-toggle--body">
645+
<div class="ais-toggle--list">
646+
<div class="ais-toggle--item">
647+
<label class="ais-toggle--label">
648+
<input type="checkbox" class="ais-toggle--checkbox" value="your_value"> Your value
649+
<span class="ais-toggle--count">42</span>
650+
</label>
651+
</div>
652+
</div>
653+
</div>
654+
<div class="ais-toggle--footer ais-footer">[custom footer template]</div>
655+
</div>
656+
```
657+
658+
```css
659+
.ais-toggle {
660+
}
661+
.ais-toggle--header {
662+
}
663+
.ais-toggle--body {
664+
}
665+
.ais-toggle--list {
666+
}
667+
.ais-toggle--item {
668+
}
669+
.ais-toggle--item__active {
670+
}
671+
.ais-toggle--label {
672+
}
673+
.ais-toggle--checkbox {
674+
}
675+
.ais-toggle--count {
676+
}
677+
.ais-toggle--footer {
678+
}
679+
```
634680
### refinementList
635681

636682
![Example of the refinementList widget][refinementList]

Diff for: example/app.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,12 @@ search.addWidget(
105105
facetName: 'free_shipping',
106106
label: 'Free Shipping',
107107
cssClasses: {
108-
header: 'panel-heading'
108+
header: 'panel-heading',
109+
item: 'panel-body',
110+
count: 'badge pull-right'
109111
},
110112
templates: {
111-
header: 'Shipping',
112-
item: require('./templates/free-shipping.html')
113+
header: 'Shipping'
113114
}
114115
})
115116
);

Diff for: example/style.css

+2-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ body {
7676
padding-left: 20px;
7777
}
7878

79-
.ais-refinement-list--label {
79+
.ais-refinement-list--label,
80+
.ais-toggle--label {
8081
display: block;
8182
}

Diff for: themes/default/default.css

+20
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@
8383
/* MENU */
8484

8585
/* TOGGLE */
86+
.ais-toggle {
87+
}
88+
.ais-toggle--header {
89+
}
90+
.ais-toggle--body {
91+
}
92+
.ais-toggle--list {
93+
}
94+
.ais-toggle--item {
95+
}
96+
.ais-toggle--item__active {
97+
}
98+
.ais-toggle--label {
99+
}
100+
.ais-toggle--checkbox {
101+
}
102+
.ais-toggle--count {
103+
}
104+
.ais-toggle--footer {
105+
}
86106

87107
/* HIERARCHICAL MENU */
88108

Diff for: widgets/toggle/__tests__/toggle-test.js

+14-5
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ describe('toggle()', () => {
1212
jsdom();
1313

1414
context('bad usage', () => {
15-
var usage = 'Usage: toggle({container, facetName, label[, template, transformData]})';
16-
1715
it('throws when no container', () => {
1816
expect(() => {
1917
toggle();
@@ -23,13 +21,13 @@ describe('toggle()', () => {
2321
it('throws when no facetName', () => {
2422
expect(() => {
2523
toggle({container: document.createElement('div')});
26-
}).toThrow(usage);
24+
}).toThrow(/Usage: /);
2725
});
2826

2927
it('throws when no label', () => {
3028
expect(() => {
3129
toggle({container: document.createElement('div'), facetName: 'Hello'});
32-
}).toThrow(usage);
30+
}).toThrow(/Usage: /);
3331
});
3432
});
3533

@@ -88,7 +86,18 @@ describe('toggle()', () => {
8886
search: sinon.spy()
8987
};
9088
props = {
91-
cssClasses: {},
89+
cssClasses: {
90+
root: 'ais-toggle',
91+
header: 'ais-toggle--header',
92+
body: 'ais-toggle--body',
93+
footer: 'ais-toggle--footer',
94+
list: 'ais-toggle--list',
95+
item: 'ais-toggle--item',
96+
active: 'ais-toggle--item__active',
97+
label: 'ais-toggle--label',
98+
checkbox: 'ais-toggle--checkbox',
99+
count: 'ais-toggle--count'
100+
},
92101
hideWhenNoResults: true,
93102
templateProps,
94103
toggleRefinement: function() {},

Diff for: widgets/toggle/defaultTemplates.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
module.exports = {
22
header: '',
3-
item: `<label>
4-
<input type="checkbox" {{#isRefined}}checked{{/isRefined}} />{{name}} <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>
56
</label>`,
67
footer: ''
78
};

Diff for: widgets/toggle/toggle.js

+27-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ var React = require('react');
33
var ReactDOM = require('react-dom');
44

55
var utils = require('../../lib/utils.js');
6+
var bem = utils.bemHelper('ais-toggle');
7+
var cx = require('classnames/dedupe');
68

79
var autoHide = require('../../decorators/autoHide');
810
var headerFooter = require('../../decorators/headerFooter');
@@ -16,15 +18,20 @@ var defaultTemplates = require('./defaultTemplates');
1618
* @param {String|DOMElement} options.container CSS Selector or DOMElement to insert the widget
1719
* @param {String} options.facetName Name of the attribute for faceting (eg. "free_shipping")
1820
* @param {String} options.label Human-readable name of the filter (eg. "Free Shipping")
19-
* @param {Object} [options.cssClasses] CSS classes to add to the wrapping elements: root, list, item
21+
* @param {Object} [options.cssClasses] CSS classes to add
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
22-
* @param {String|String[]} [options.cssClasses.item] CSS class to add to the item element
27+
* @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
2433
* @param {String|Function} [options.templates.header=''] Header template
25-
* @param {String|Function} [options.templates.item='<label>
26-
<input type="checkbox" {{#isRefined}}checked{{/isRefined}} />{{name}} <span>{{count}}</span>
27-
</label>'] Item template
34+
* @param {String|Function} [options.templates.item] Item template
2835
* @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
@@ -41,9 +48,9 @@ function toggle({
4148
} = {}) {
4249
var RefinementList = autoHide(headerFooter(require('../../components/RefinementList')));
4350
var containerNode = utils.getContainerNode(container);
44-
var usage = 'Usage: toggle({container, facetName, label[, template, transformData]})';
51+
var usage = 'Usage: toggle({container, facetName, label[, cssClasses.{root,header,body,footer,list,item,active,label,checkbox,count}, templates.{header,item,footer}, transformData, hideWhenNoResults]})';
4552

46-
if (container === undefined || facetName === undefined || label === undefined) {
53+
if (!container || !facetName || !label) {
4754
throw new Error(usage);
4855
}
4956

@@ -68,6 +75,19 @@ function toggle({
6875
count: values && values.count || null
6976
};
7077

78+
cssClasses = {
79+
root: cx(bem(null), cssClasses.root),
80+
header: cx(bem('header'), cssClasses.header),
81+
body: cx(bem('body'), cssClasses.body),
82+
footer: cx(bem('footer'), cssClasses.footer),
83+
list: cx(bem('list'), cssClasses.list),
84+
item: cx(bem('item'), cssClasses.item),
85+
active: cx(bem('item', 'active'), cssClasses.active),
86+
label: cx(bem('label'), cssClasses.label),
87+
checkbox: cx(bem('checkbox'), cssClasses.checkbox),
88+
count: cx(bem('count'), cssClasses.count)
89+
};
90+
7191
ReactDOM.render(
7292
<RefinementList
7393
createURL={() => createURL(state.toggleRefinement(facetName, facetValue.isRefined))}

0 commit comments

Comments
 (0)