Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

feat(chips): Change chip color when selected #2329

Merged
merged 6 commits into from
Mar 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demos/chips.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
.custom-chip-secondary {
@include mdc-chip-fill-color(white);
@include mdc-chip-ink-color($mdc-theme-secondary);
@include mdc-chip-selected-ink-color($mdc-theme-secondary);
@include mdc-chip-stroke(2px, solid, $mdc-theme-secondary);
}
8 changes: 3 additions & 5 deletions packages/mdc-chips/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,14 @@ Mixin | Description
`mdc-chip-fill-color-accessible($color)` | Customizes the background fill color for a chip, and updates the chip's ink and ripple color to meet accessibility standards
`mdc-chip-fill-color($color)` | Customizes the background fill color for a chip
`mdc-chip-ink-color($color)` | Customizes the text ink color for a chip, and updates the chip's ripple color to match
`mdc-chip-activated-ink-color($color)` | Customizes text ink color and updates the ripple opacity of a chip in the _activated_ state
`mdc-chip-selected-ink-color($color)` | Customizes text ink and ripple color of a chip in the _selected_ state
`mdc-chip-stroke($width, $style, $color)` | Customizes the border stroke properties for a chip
`mdc-chip-stroke-width($width)` | Customizes the border stroke width for a chip
`mdc-chip-stroke-style($style)` | Customizes the border stroke style for a chip
`mdc-chip-stroke-color($color)` | Customizes the border stroke color for a chip

> _NOTE_: `mdc-chip-set-spacing` also sets the amount of space between a chip and the edge of the set it's contained in.

> _NOTE_: `mdc-chip-ink-color` also updates the chip's text ink color for _hover_ and _activated_ states, and updates the ripple opacity of the chip in the _activated_ state.

### `MDCChip` and `MDCChipSet`

The MDC Chips module is comprised of two JavaScript classes:
Expand All @@ -122,7 +120,7 @@ To use the `MDCChip` and `MDCChipSet` classes, [import](../../docs/importing-js.

Method Signature | Description
--- | ---
`toggleActive() => void` | Proxies to the foundation's `toggleActive` method
`toggleSelected() => void` | Proxies to the foundation's `toggleSelected` method

Property | Value Type | Description
--- | --- | ---
Expand Down Expand Up @@ -164,7 +162,7 @@ Method Signature | Description

Method Signature | Description
--- | ---
`toggleActive() => void` | Toggles the activated class on the chip element
`toggleSelected() => void` | Toggles the selected class on the chip element

#### `MDCChipSetFoundation`
None yet, coming soon.
19 changes: 10 additions & 9 deletions packages/mdc-chips/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@

@if ($fill-tone == "dark") {
@include mdc-chip-ink-color(text-primary-on-dark);
@include mdc-chip-activated-ink-color(white);
@include mdc-chip-selected-ink-color(white);
} @else {
@include mdc-chip-ink-color(text-primary-on-light);
@include mdc-chip-activated-ink-color(black);
@include mdc-chip-selected-ink-color(black);
}
}

Expand All @@ -42,23 +42,24 @@

@mixin mdc-chip-ink-color($color) {
@include mdc-states($color);
@include mdc-chip-activated-ink-color($color);
@include mdc-theme-prop(color, $color);

&:hover {
@include mdc-theme-prop(color, $color);
}
}

@mixin mdc-chip-activated-ink-color($activated-ink-color) {
@mixin mdc-chip-selected-ink-color($color) {
&.mdc-chip {
// This changes the opacity of the ripple based on whether $activated-ink-color is light or dark.
// It does not change the color of the ripple.
@include mdc-states-activated($activated-ink-color);
@include mdc-states-selected($color);
}

&.mdc-chip--activated {
@include mdc-theme-prop(color, $activated-ink-color);
&.mdc-chip--selected {
@include mdc-theme-prop(color, $color);

&:hover {
@include mdc-theme-prop(color, $color);
}
}
}

Expand Down
26 changes: 13 additions & 13 deletions packages/mdc-chips/chip-set/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ class MDCChipSetFoundation extends MDCFoundation {
super(Object.assign(MDCChipSetFoundation.defaultAdapter, adapter));

/**
* The active chips in the set. Only used for choice chip set or filter chip set.
* The selected chips in the set. Only used for choice chip set or filter chip set.
* @private {!Array<!MDCChip>}
*/
this.activeChips_ = [];
this.selectedChips_ = [];

/** @private {function(!Event): undefined} */
this.chipInteractionHandler_ = (evt) => this.handleChipInteraction_(evt);
Expand All @@ -83,23 +83,23 @@ class MDCChipSetFoundation extends MDCFoundation {
handleChipInteraction_(evt) {
const {chip} = evt.detail;
if (this.adapter_.hasClass(cssClasses.CHOICE)) {
if (this.activeChips_.length === 0) {
this.activeChips_[0] = chip;
} else if (this.activeChips_[0] !== chip) {
this.activeChips_[0].toggleActive();
this.activeChips_[0] = chip;
if (this.selectedChips_.length === 0) {
this.selectedChips_[0] = chip;
} else if (this.selectedChips_[0] !== chip) {
this.selectedChips_[0].toggleSelected();
this.selectedChips_[0] = chip;
} else {
this.activeChips_ = [];
this.selectedChips_ = [];
}
chip.toggleActive();
chip.toggleSelected();
} else if (this.adapter_.hasClass(cssClasses.FILTER)) {
const index = this.activeChips_.indexOf(chip);
const index = this.selectedChips_.indexOf(chip);
if (index >= 0) {
this.activeChips_.splice(index, 1);
this.selectedChips_.splice(index, 1);
} else {
this.activeChips_.push(chip);
this.selectedChips_.push(chip);
}
chip.toggleActive();
chip.toggleSelected();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/mdc-chips/chip/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const strings = {

/** @enum {string} */
const cssClasses = {
ACTIVATED: 'mdc-chip--activated',
SELECTED: 'mdc-chip--selected',
};

export {strings, cssClasses};
10 changes: 5 additions & 5 deletions packages/mdc-chips/chip/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ class MDCChipFoundation extends MDCFoundation {
}

/**
* Toggles the activated class on the chip element.
* Toggles the selected class on the chip element.
*/
toggleActive() {
if (this.adapter_.hasClass(cssClasses.ACTIVATED)) {
this.adapter_.removeClass(cssClasses.ACTIVATED);
toggleSelected() {
if (this.adapter_.hasClass(cssClasses.SELECTED)) {
this.adapter_.removeClass(cssClasses.SELECTED);
} else {
this.adapter_.addClass(cssClasses.ACTIVATED);
this.adapter_.addClass(cssClasses.SELECTED);
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/mdc-chips/chip/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ class MDCChip extends MDCComponent {
}

/**
* Toggles active state of the chip.
* Toggles selected state of the chip.
*/
toggleActive() {
this.foundation_.toggleActive();
toggleSelected() {
this.foundation_.toggleSelected();
}

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/mdc-chips/chip/mdc-chip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@include mdc-chip-corner-radius($mdc-chip-border-radius-default);
@include mdc-chip-fill-color($mdc-chip-fill-color-default);
@include mdc-chip-ink-color($mdc-chip-ink-color-default);
@include mdc-chip-activated-ink-color(black);
@include mdc-chip-selected-ink-color(primary);

display: inline-flex;
position: relative;
Expand All @@ -42,6 +42,10 @@
}
}

.mdc-chip--selected {
@include mdc-theme-prop(background-color, white);
}

.mdc-chip__text {
// Set line-height to be <18px to force the content height of mdc-chip to be 18px.
line-height: 17px;
Expand Down
42 changes: 21 additions & 21 deletions test/unit/mdc-chips/mdc-chip-set.foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ const setupTest = () => {
const mockAdapter = td.object(MDCChipSetFoundation.defaultAdapter);
const foundation = new MDCChipSetFoundation(mockAdapter);
const chipA = td.object({
toggleActive: () => {},
toggleSelected: () => {},
});
const chipB = td.object({
toggleActive: () => {},
toggleSelected: () => {},
});
return {foundation, mockAdapter, chipA, chipB};
};
Expand All @@ -64,7 +64,7 @@ test('#destroy removes event listeners', () => {
td.verify(mockAdapter.deregisterInteractionHandler('MDCChip:interaction', td.matchers.isA(Function)));
});

test('on custom MDCChip:interaction event toggles active state with single selection on choice chips', () => {
test('on custom MDCChip:interaction event toggles selected state with single selection on choice chips', () => {
const {foundation, mockAdapter, chipA, chipB} = setupTest();
let chipInteractionHandler;
td.when(mockAdapter.registerInteractionHandler('MDCChip:interaction', td.matchers.isA(Function)))
Expand All @@ -73,36 +73,36 @@ test('on custom MDCChip:interaction event toggles active state with single selec
});
td.when(mockAdapter.hasClass(cssClasses.CHOICE)).thenReturn(true);

assert.equal(foundation.activeChips_.length, 0);
assert.equal(foundation.selectedChips_.length, 0);
foundation.init();

chipInteractionHandler({
detail: {
chip: chipA,
},
});
td.verify(chipA.toggleActive());
assert.equal(foundation.activeChips_.length, 1);
td.verify(chipA.toggleSelected());
assert.equal(foundation.selectedChips_.length, 1);

chipInteractionHandler({
detail: {
chip: chipB,
},
});
td.verify(chipA.toggleActive());
td.verify(chipB.toggleActive());
assert.equal(foundation.activeChips_.length, 1);
td.verify(chipA.toggleSelected());
td.verify(chipB.toggleSelected());
assert.equal(foundation.selectedChips_.length, 1);

chipInteractionHandler({
detail: {
chip: chipB,
},
});
td.verify(chipB.toggleActive());
assert.equal(foundation.activeChips_.length, 0);
td.verify(chipB.toggleSelected());
assert.equal(foundation.selectedChips_.length, 0);
});

test('on custom MDCChip:interaction event toggles active state with multi-selection on filter chips', () => {
test('on custom MDCChip:interaction event toggles selected state with multi-selection on filter chips', () => {
const {foundation, mockAdapter, chipA, chipB} = setupTest();
let chipInteractionHandler;
td.when(mockAdapter.registerInteractionHandler('MDCChip:interaction', td.matchers.isA(Function)))
Expand All @@ -111,38 +111,38 @@ test('on custom MDCChip:interaction event toggles active state with multi-select
});
td.when(mockAdapter.hasClass(cssClasses.FILTER)).thenReturn(true);

assert.equal(foundation.activeChips_.length, 0);
assert.equal(foundation.selectedChips_.length, 0);
foundation.init();

chipInteractionHandler({
detail: {
chip: chipA,
},
});
td.verify(chipA.toggleActive());
assert.equal(foundation.activeChips_.length, 1);
td.verify(chipA.toggleSelected());
assert.equal(foundation.selectedChips_.length, 1);

chipInteractionHandler({
detail: {
chip: chipB,
},
});
td.verify(chipB.toggleActive());
assert.equal(foundation.activeChips_.length, 2);
td.verify(chipB.toggleSelected());
assert.equal(foundation.selectedChips_.length, 2);

chipInteractionHandler({
detail: {
chip: chipB,
},
});
td.verify(chipB.toggleActive());
assert.equal(foundation.activeChips_.length, 1);
td.verify(chipB.toggleSelected());
assert.equal(foundation.selectedChips_.length, 1);

chipInteractionHandler({
detail: {
chip: chipA,
},
});
td.verify(chipA.toggleActive());
assert.equal(foundation.activeChips_.length, 0);
td.verify(chipA.toggleSelected());
assert.equal(foundation.selectedChips_.length, 0);
});
16 changes: 8 additions & 8 deletions test/unit/mdc-chips/mdc-chip.foundation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,20 @@ test('#destroy removes event listeners', () => {
td.verify(mockAdapter.deregisterTrailingIconInteractionHandler('mousedown', td.matchers.isA(Function)));
});

test('#toggleActive adds mdc-chip--activated class if the class does not exist', () => {
test('#toggleSelected adds mdc-chip--selected class if the class does not exist', () => {
const {foundation, mockAdapter} = setupTest();
td.when(mockAdapter.hasClass(cssClasses.ACTIVATED)).thenReturn(false);
td.when(mockAdapter.hasClass(cssClasses.SELECTED)).thenReturn(false);

foundation.toggleActive();
td.verify(mockAdapter.addClass(cssClasses.ACTIVATED));
foundation.toggleSelected();
td.verify(mockAdapter.addClass(cssClasses.SELECTED));
});

test('#toggleActive removes mdc-chip--activated class if the class exists', () => {
test('#toggleSelected removes mdc-chip--selected class if the class exists', () => {
const {foundation, mockAdapter} = setupTest();
td.when(mockAdapter.hasClass(cssClasses.ACTIVATED)).thenReturn(true);
td.when(mockAdapter.hasClass(cssClasses.SELECTED)).thenReturn(true);

foundation.toggleActive();
td.verify(mockAdapter.removeClass(cssClasses.ACTIVATED));
foundation.toggleSelected();
td.verify(mockAdapter.removeClass(cssClasses.SELECTED));
});

test('on click, emit custom event', () => {
Expand Down
6 changes: 3 additions & 3 deletions test/unit/mdc-chips/mdc-chip.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ function setupMockFoundationTest(root = getFixture()) {
return {root, component, mockFoundation};
}

test('#toggleActive proxies to foundation', () => {
test('#toggleSelected proxies to foundation', () => {
const {component, mockFoundation} = setupMockFoundationTest();
component.toggleActive();
td.verify(mockFoundation.toggleActive());
component.toggleSelected();
td.verify(mockFoundation.toggleSelected());
});