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

Commit f89cd10

Browse files
authored
feat(chips): Add mdc-chip-set--choice variant (#2215)
Add choice chips, which allow single selection from a set of chip options.
1 parent e1e50cc commit f89cd10

18 files changed

+324
-9
lines changed

demos/chips.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ <h2>Entry Chips</h2>
7171

7272
<section class="example">
7373
<h2>Choice Chips</h2>
74-
<div class="mdc-chip-set">
74+
<div class="mdc-chip-set mdc-chip-set--choice">
7575
<div class="demo-chip mdc-chip" tabindex="0">
7676
<div class="mdc-chip__text">Extra Small</div>
7777
</div>

packages/mdc-chips/README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ You can optionally add a leading icon (i.e. thumbnail) and/or a trailing icon to
7979
CSS Class | Description
8080
--- | ---
8181
`mdc-chip-set` | Mandatory. Indicates the set that the chip belongs to
82+
`mdc-chip-set--choice` | Optional. Indicates that the chips in the set are choice chips, which allow a single selection from a set of options.
8283
`mdc-chip` | Mandatory.
8384
`mdc-chip__text` | Mandatory. Indicates the text content of the chip
8485
`mdc-chip__icon` | Optional. Indicates an icon in the chip
@@ -97,11 +98,14 @@ Mixin | Description
9798
`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
9899
`mdc-chip-fill-color($color)` | Customizes the background fill color for a chip
99100
`mdc-chip-ink-color($color)` | Customizes the text ink color for a chip, and updates the chip's ripple color to match
101+
`mdc-chip-activated-ink-color($color)` | Customizes text ink color and updates the ripple opacity of a chip in the _activated_ state
100102
`mdc-chip-stroke($width, $style, $color)` | Customizes the border stroke properties for a chip
101103
`mdc-chip-stroke-width($width)` | Customizes the border stroke width for a chip
102104
`mdc-chip-stroke-style($style)` | Customizes the border stroke style for a chip
103105
`mdc-chip-stroke-color($color)` | Customizes the border stroke color for a chip
104106

107+
> _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.
108+
105109
### `MDCChip` and `MDCChipSet`
106110

107111
The MDC Chips module is comprised of two JavaScript classes:
@@ -112,6 +116,10 @@ To use the `MDCChip` and `MDCChipSet` classes, [import](../../docs/importing-js.
112116

113117
#### `MDCChip`
114118

119+
Method Signature | Description
120+
--- | ---
121+
`toggleActive() => void` | Proxies to the foundation's `toggleActive` method
122+
115123
Property | Value Type | Description
116124
--- | --- | ---
117125
`ripple` | `MDCRipple` | The `MDCRipple` instance for the root element that `MDCChip` initializes
@@ -128,6 +136,9 @@ Property | Value Type | Description
128136

129137
Method Signature | Description
130138
--- | ---
139+
`addClass(className: string) => void` | Adds a class to the root element
140+
`removeClass(className: string) => void` | Removes a class from the root element
141+
`hasClass(className: string) => boolean` | Returns true if the root element contains the given class
131142
`registerInteractionHandler(evtType: string, handler: EventListener) => void` | Registers an event listener on the root element
132143
`deregisterInteractionHandler(evtType: string, handler: EventListener) => void` | Deregisters an event listener on the root element
133144
`notifyInteraction() => void` | Emits a custom event "MDCChip:interaction" denoting the chip has been interacted with, which bubbles to the parent `mdc-chip-set` element
@@ -137,11 +148,16 @@ Method Signature | Description
137148
Method Signature | Description
138149
--- | ---
139150
`hasClass(className: string) => boolean` | Returns whether the chip set element has the given class
151+
`registerInteractionHandler(evtType, handler) => void` | Registers an event handler on the root element for a given event
152+
`deregisterInteractionHandler(evtType, handler) => void` | Deregisters an event handler on the root element for a given event
140153

141154
### Foundations: `MDCChipFoundation` and `MDCChipSetFoundation`
142155

143156
#### `MDCChipFoundation`
144-
None yet, coming soon.
157+
158+
Method Signature | Description
159+
--- | ---
160+
`toggleActive() => void` | Toggles the activated class on the chip element
145161

146162
#### `MDCChipSetFoundation`
147163
None yet, coming soon.

packages/mdc-chips/_mixins.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929

3030
@if ($fill-tone == "dark") {
3131
@include mdc-chip-ink-color(text-primary-on-dark);
32+
@include mdc-chip-activated-ink-color(white);
3233
} @else {
3334
@include mdc-chip-ink-color(text-primary-on-light);
35+
@include mdc-chip-activated-ink-color(black);
3436
}
3537
}
3638

@@ -40,7 +42,24 @@
4042

4143
@mixin mdc-chip-ink-color($color) {
4244
@include mdc-states($color);
45+
@include mdc-chip-activated-ink-color($color);
4346
@include mdc-theme-prop(color, $color);
47+
48+
&:hover {
49+
@include mdc-theme-prop(color, $color);
50+
}
51+
}
52+
53+
@mixin mdc-chip-activated-ink-color($activated-ink-color) {
54+
&.mdc-chip {
55+
// This changes the opacity of the ripple based on whether $activated-ink-color is light or dark.
56+
// It does not change the color of the ripple.
57+
@include mdc-states-activated($activated-ink-color);
58+
}
59+
60+
&.mdc-chip--activated {
61+
@include mdc-theme-prop(color, $activated-ink-color);
62+
}
4463
}
4564

4665
@mixin mdc-chip-stroke($width: 1, $style: solid, $color: black) {

packages/mdc-chips/_variables.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
$mdc-chip-border-radius-default: 16px;
1818
$mdc-chip-fill-color-default: rgba(black, .08);
19+
$mdc-chip-ink-color-default: rgba(black, .6);
1920
$mdc-chip-horizontal-padding: 12px;
2021
$mdc-chip-vertical-padding: 7px;
2122

packages/mdc-chips/chip-set/adapter.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,23 @@ class MDCChipSetAdapter {
3131
/**
3232
* Returns true if the root element contains the given class name.
3333
* @param {string} className
34+
* @return {boolean}
3435
*/
3536
hasClass(className) {}
37+
38+
/**
39+
* Registers an event handler on the root element for a given event.
40+
* @param {string} evtType
41+
* @param {function(!Event): undefined} handler
42+
*/
43+
registerInteractionHandler(evtType, handler) {}
44+
45+
/**
46+
* Deregisters an event handler on the root element for a given event.
47+
* @param {string} evtType
48+
* @param {function(!Event): undefined} handler
49+
*/
50+
deregisterInteractionHandler(evtType, handler) {}
3651
}
3752

3853
export default MDCChipSetAdapter;

packages/mdc-chips/chip-set/constants.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ const strings = {
2020
CHIP_SELECTOR: '.mdc-chip',
2121
};
2222

23-
export {strings};
23+
/** @enum {string} */
24+
const cssClasses = {
25+
CHOICE: 'mdc-chip-set--choice',
26+
};
27+
28+
export {strings, cssClasses};

packages/mdc-chips/chip-set/foundation.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
import MDCFoundation from '@material/base/foundation';
1919
import MDCChipSetAdapter from './adapter';
20-
import {strings} from './constants';
20+
// eslint-disable-next-line no-unused-vars
21+
import {MDCChip, MDCChipFoundation} from '../chip/index';
22+
import {strings, cssClasses} from './constants';
2123

2224
/**
2325
* @extends {MDCFoundation<!MDCChipSetAdapter>}
@@ -29,6 +31,11 @@ class MDCChipSetFoundation extends MDCFoundation {
2931
return strings;
3032
}
3133

34+
/** @return enum {string} */
35+
static get cssClasses() {
36+
return cssClasses;
37+
}
38+
3239
/**
3340
* {@see MDCChipSetAdapter} for typing information on parameters and return
3441
* types.
@@ -37,6 +44,8 @@ class MDCChipSetFoundation extends MDCFoundation {
3744
static get defaultAdapter() {
3845
return /** @type {!MDCChipSetAdapter} */ ({
3946
hasClass: () => {},
47+
registerInteractionHandler: () => {},
48+
deregisterInteractionHandler: () => {},
4049
});
4150
}
4251

@@ -45,6 +54,46 @@ class MDCChipSetFoundation extends MDCFoundation {
4554
*/
4655
constructor(adapter) {
4756
super(Object.assign(MDCChipSetFoundation.defaultAdapter, adapter));
57+
58+
/**
59+
* The active chips in the set. Only used for choice chip set or filter chip set.
60+
* @private {!Array<!MDCChip>}
61+
*/
62+
this.activeChips_ = [];
63+
64+
/** @private {function(!Event): undefined} */
65+
this.chipInteractionHandler_ = (evt) => this.handleChipInteraction_(evt);
66+
}
67+
68+
init() {
69+
this.adapter_.registerInteractionHandler(
70+
MDCChipFoundation.strings.INTERACTION_EVENT, this.chipInteractionHandler_);
71+
}
72+
73+
destroy() {
74+
this.adapter_.deregisterInteractionHandler(
75+
MDCChipFoundation.strings.INTERACTION_EVENT, this.chipInteractionHandler_);
76+
}
77+
78+
/**
79+
* Handles a chip interaction event
80+
* @param {!Object} evt
81+
* @private
82+
*/
83+
handleChipInteraction_(evt) {
84+
if (!this.adapter_.hasClass(cssClasses.CHOICE)) {
85+
return;
86+
}
87+
const {chip} = evt.detail;
88+
if (this.activeChips_.length === 0) {
89+
this.activeChips_[0] = chip;
90+
} else if (this.activeChips_[0] !== chip) {
91+
this.activeChips_[0].toggleActive();
92+
this.activeChips_[0] = chip;
93+
} else {
94+
this.activeChips_ = [];
95+
}
96+
chip.toggleActive();
4897
}
4998
}
5099

packages/mdc-chips/chip-set/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class MDCChipSet extends MDCComponent {
3232
constructor(...args) {
3333
super(...args);
3434

35-
/** @private {!Array<!MDCChip>} */
35+
/** @type {!Array<!MDCChip>} */
3636
this.chips;
3737
}
3838

@@ -64,6 +64,8 @@ class MDCChipSet extends MDCComponent {
6464
getDefaultFoundation() {
6565
return new MDCChipSetFoundation(/** @type {!MDCChipSetAdapter} */ (Object.assign({
6666
hasClass: (className) => this.root_.classList.contains(className),
67+
registerInteractionHandler: (evtType, handler) => this.root_.addEventListener(evtType, handler),
68+
deregisterInteractionHandler: (evtType, handler) => this.root_.removeEventListener(evtType, handler),
6769
})));
6870
}
6971

packages/mdc-chips/chip/adapter.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@
2828
* @record
2929
*/
3030
class MDCChipAdapter {
31+
/**
32+
* Adds a class to the root element.
33+
* @param {string} className
34+
*/
35+
addClass(className) {}
36+
37+
/**
38+
* Removes a class from the root element.
39+
* @param {string} className
40+
*/
41+
removeClass(className) {}
42+
43+
/**
44+
* Returns true if the root element contains the given class.
45+
* @param {string} className
46+
* @return {boolean}
47+
*/
48+
hasClass(className) {}
49+
3150
/**
3251
* Registers an event listener on the root element for a given event.
3352
* @param {string} evtType

packages/mdc-chips/chip/constants.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ const strings = {
2020
INTERACTION_EVENT: 'MDCChip:interaction',
2121
};
2222

23-
export {strings};
23+
/** @enum {string} */
24+
const cssClasses = {
25+
ACTIVATED: 'mdc-chip--activated',
26+
};
27+
28+
export {strings, cssClasses};

0 commit comments

Comments
 (0)