Skip to content

Commit

Permalink
fix(structured-list): label > input for better react porting (#192)
Browse files Browse the repository at this point in the history
* test(structured-list): update options

* fix(structured-list): label > input refactor for better react porting

* style(structured-list): prettier

* docs(structured-list): update docs with new options

* test(structured-list): click event

* test(structured-list): add test for toggling classActive
  • Loading branch information
hellobrian authored and iangfleming committed Jun 26, 2017
1 parent 42144c2 commit 0320771
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 23 deletions.
14 changes: 8 additions & 6 deletions src/components/structured-list/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ All mixins listed below take an optional `$padding` parameter. Default value for

Use these modifiers with `.bx--structured-list` class.

| Selector | Description |
|--------------------------------------|----------------------------------------------------------------------------------------------|
| .bx--structured-list--border | Applies border around structured-list and white background-color |
| .bx--structured-list--condensed | Applies condensed styles for all body rows |
| .bx--structured-list-content--nowrap | Applies `white-space: nowrap;` on content. Prevents titles from wrapping in small viewports. |
| .bx--structured-list--selection | Applies styles used for selection variant of structured-list. |
| Selector | Description |
|--------------------------------------|--------------------------------------------------------------------------------------------------------------|
| .bx--structured-list--border | Applies border around structured-list and white background-color |
| .bx--structured-list--condensed | Applies condensed styles for all body rows |
| .bx--structured-list-content--nowrap | Applies `white-space: nowrap;` on content. Prevents titles from wrapping in small viewports. |
| .bx--structured-list--selection | Applies styles used for selection variant of structured-list. |
| .bx--structured-list-row--selected | Applies modifier class to label row. This changes the background color to indicate that the row is selected. |


Use these modifiers with `.bx--structured-list-td` class.
Expand All @@ -46,6 +47,7 @@ Use these modifiers with `.bx--structured-list-td` class.
|-----------------------|-------------------------------------------------------|--------------------------------------------------|
| `selectorInit` | `[data-structured-list]` | The selector to find the StructuredList element. |
| `selectorStepElement` | `.bx--structured-list-tbody .bx--structured-list-row` | The selector to find the step element. |
| `classActive` | `'bx--structured-list-row--selected'` | The class to indicate a selected row |

### FAQ

Expand Down
17 changes: 9 additions & 8 deletions src/components/structured-list/_structured-list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
}

.bx--structured-list-input {
@include hidden;
display: none;
}

.bx--structured-list {
Expand Down Expand Up @@ -61,7 +61,7 @@
cursor: pointer;
}

.bx--structured-list-input:checked + & {
&.bx--structured-list-row--selected {
background-color: rgba($brand-02, .1);
}

Expand Down Expand Up @@ -107,11 +107,6 @@
display: table-cell;
}

// Deprecated class
.bx--structured-list-content {
@include font-size('14');
}

.bx--structured-list-content--nowrap {
white-space: nowrap;
}
Expand All @@ -126,8 +121,14 @@
fill: rgba($brand-02, .1);
}

.bx--structured-list-input:checked + .bx--structured-list-row & {
.bx--structured-list-input:checked + .bx--structured-list-row &,
.bx--structured-list-input:checked + .bx--structured-list-td & {
fill: $brand-02;
}
}

// Deprecated class
.bx--structured-list-content {
@include font-size('14');
}
}
17 changes: 8 additions & 9 deletions src/components/structured-list/structured-list--selection.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
</div>
</div>
<div class="bx--structured-list-tbody">
<input tabindex="-1" id="apache-id" class="bx--structured-list-input" value="apache spark" type="radio" name="services" title="apache spark"
checked />
<label for="apache-id" aria-label="apache spark" class="bx--structured-list-row" tabindex="0">
<label for="apache-id" aria-label="apache spark" class="bx--structured-list-row bx--structured-list-row--selected" tabindex="0">
<input tabindex="-1" id="apache-id" class="bx--structured-list-input" value="apache spark" type="radio" name="services" title="apache spark"
checked />
<div class="bx--structured-list-td">
<svg class="bx--structured-list-svg" width="16" height="16" viewBox="0 0 16 16" fill-rule="evenodd">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM6.7 11.5L3.4 8.1l1.4-1.4 1.9 1.9 4.1-4.1 1.4 1.4-5.5 5.6z">
Expand All @@ -23,9 +23,9 @@
Apache Spark is an open source cluster computing framework optimized for extremely fast and large scale data processing, which you can access via the newly integrated notebook interface IBM Analytics for Apache Spark.
</div>
</label>
<input tabindex="-1" id="cloudant-id" class="bx--structured-list-input" value="Cloudant" type="radio" name="services" title="Cloudant"
/>
<label for="cloudant-id" aria-label="Cloudant" class="bx--structured-list-row" tabindex="0">
<input tabindex="-1" id="cloudant-id" class="bx--structured-list-input" value="Cloudant" type="radio" name="services" title="Cloudant"
/>
<div class="bx--structured-list-td">
<svg class="bx--structured-list-svg" width="16" height="16" viewBox="0 0 16 16" fill-rule="evenodd">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM6.7 11.5L3.4 8.1l1.4-1.4 1.9 1.9 4.1-4.1 1.4 1.4-5.5 5.6z">
Expand All @@ -36,9 +36,9 @@
<div class="bx--structured-list-td">IBM</div>
<div class="bx--structured-list-td">Cloudant NoSQL DB is a fully managed data layer designed for modern web and mobile applications that leverages a flexible JSON schema.</div>
</label>
<input tabindex="-1" id="block-storate-id" class="bx--structured-list-input" value="block-storage" type="radio" name="services"
title="block-storage" />
<label for="block-storate-id" aria-label="Cloudant" class="bx--structured-list-row" tabindex="0">
<input tabindex="-1" id="block-storate-id" class="bx--structured-list-input" value="block-storage" type="radio" name="services"
title="block-storage" />
<div class="bx--structured-list-td">
<svg class="bx--structured-list-svg" width="16" height="16" viewBox="0 0 16 16" fill-rule="evenodd">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM6.7 11.5L3.4 8.1l1.4-1.4 1.9 1.9 4.1-4.1 1.4 1.4-5.5 5.6z">
Expand All @@ -49,9 +49,8 @@
<div class="bx--structured-list-td">IBM</div>
<div class="bx--structured-list-td">Get local disk performance with SAN persistence and durability. Increase storage capacity available to your Bluemix Virtual and Bare Metal Servers with a maximum of 48k IOPs.*</div>
</label>
<input tabindex="-1" id="open-whisk-id" class="bx--structured-list-input" value="open-whisk" type="radio" name="services"
title="open-whisk" />
<label for="open-whisk-id" aria-label="Cloudant" class="bx--structured-list-row" tabindex="0">
<input tabindex="-1" id="open-whisk-id" class="bx--structured-list-input" value="open-whisk" type="radio" name="services" title="open-whisk" />
<div class="bx--structured-list-td">
<svg class="bx--structured-list-svg" width="16" height="16" viewBox="0 0 16 16" fill-rule="evenodd">
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM6.7 11.5L3.4 8.1l1.4-1.4 1.9 1.9 4.1-4.1 1.4 1.4-5.5 5.6z">
Expand Down
24 changes: 24 additions & 0 deletions src/components/structured-list/structured-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class StructuredList extends mixin(createComponent, initComponentBySearch) {
this._handleKeydownChecked(evt);
}
});
this.element.addEventListener('click', (evt) => {
this._handleClick(evt);
});
}

_direction(evt) {
Expand All @@ -47,36 +50,56 @@ class StructuredList extends mixin(createComponent, initComponentBySearch) {
input.checked = true;
}

_handleClick(evt) {
const selectedRow = eventMatches(evt, this.options.selectorRow);
[...this.element.querySelectorAll(this.options.selectorRow)].forEach(row =>
row.classList.remove(this.options.classActive),
);
if (selectedRow) {
selectedRow.classList.add(this.options.classActive);
}
}

// Handle Enter or Space keydown events for selecting <label> rows
_handleKeydownChecked(evt) {
const selectedRow = eventMatches(evt, this.options.selectorRow);
[...this.element.querySelectorAll(this.options.selectorRow)].forEach(row =>
row.classList.remove(this.options.classActive),
);
if (selectedRow) {
selectedRow.classList.add(this.options.classActive);
const input = this.element.querySelector(
`#${selectedRow.getAttribute('for')}.bx--structured-list-input`,
);
input.checked = true;
}
}

// Handle up and down keydown events for selecting <label> rows
_handleKeydownArrow(evt) {
const selectedRow = eventMatches(evt, this.options.selectorRow);
const direction = this._direction(evt);

if (direction && selectedRow !== undefined) {
const rows = [...this.element.querySelectorAll(this.options.selectorRow)];
rows.forEach(row => row.classList.remove(this.options.classActive));
const firstIndex = 0;
const nextIndex = this._nextIndex(rows, selectedRow, direction);
const lastIndex = rows.length - 1;

switch (nextIndex) {
case -1:
rows[lastIndex].classList.add(this.options.classActive);
rows[lastIndex].focus();
this._handleInputChecked(lastIndex);
break;
case rows.length:
rows[firstIndex].classList.add(this.options.classActive);
rows[firstIndex].focus();
this._handleInputChecked(firstIndex);
break;
default:
rows[nextIndex].classList.add(this.options.classActive);
rows[nextIndex].focus();
this._handleInputChecked(nextIndex);
break;
Expand All @@ -90,6 +113,7 @@ class StructuredList extends mixin(createComponent, initComponentBySearch) {
selectorInit: '[data-structured-list]',
selectorRow:
'[data-structured-list] .bx--structured-list-tbody > label.bx--structured-list-row',
classActive: 'bx--structured-list-row--selected',
};
}

Expand Down
45 changes: 45 additions & 0 deletions tests/spec/structured-list_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('StructuredList', function () {
selectorInit: '[data-structured-list]',
selectorRow:
'[data-structured-list] .bx--structured-list-tbody > label.bx--structured-list-row',
classActive: 'bx--structured-list-row--selected',
});
});

Expand Down Expand Up @@ -99,6 +100,50 @@ describe('StructuredList', function () {
});
});

describe('_handleClick(evt)', function () {
let instance;
let element;
let wrapper;
let spy;

beforeEach(function () {
wrapper = document.createElement('div');
wrapper.innerHTML = HTML;
document.body.appendChild(wrapper);
element = document.querySelector('[data-structured-list]');
instance = new StructuredList(element);
});

it('should be called on "click" keydown event', function () {
spy = sinon.spy(instance, '_handleClick');
const event = Object.assign(
new CustomEvent('click', {
bubbles: true,
}),
);
instance.element.dispatchEvent(event);
expect(spy).to.have.been.called;
});

it('should toggle classActive on a selectorRow', function () {
spy = sinon.spy(instance, '_handleClick');
const event = Object.assign(
new CustomEvent('click', {
bubbles: true,
}),
);
const rows = instance.element.querySelectorAll(instance.options.selectorRow);
rows[1].dispatchEvent(event);
expect(rows[1].classList.contains(instance.options.classActive)).to.equal(true);
});

afterEach(function () {
spy.restore();
instance.release();
document.body.removeChild(wrapper);
});
});

describe('_direction(evt)', function () {
let instance;
let element;
Expand Down

0 comments on commit 0320771

Please sign in to comment.