-
Notifications
You must be signed in to change notification settings - Fork 6.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(chips): Add removal functionality/styling. #4912
Conversation
33174bb
to
03d293e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for picking this up
src/demo-app/chips/chips-demo.ts
Outdated
@@ -39,13 +46,29 @@ export class ChipsDemo { | |||
alert(message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you're in here, could you change this to literally anything but an alert
?
src/demo-app/chips/chips-demo.html
Outdated
<md-input-container> | ||
<input mdInput #input (keyup.enter)="add(input)" placeholder="New Contributor..."/> | ||
<md-input-container mdChipListContainer> | ||
<md-chip-list mdPrefix #chipList> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the chip-list inside of input-container going to change in a follow-up PR?
src/demo-app/chips/chips-demo.ts
Outdated
let value = event.value; | ||
|
||
// Add our person | ||
if (value && value.trim() != '') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could change this to if ((value || '').trim())
src/lib/chips/_chips-theme.scss
Outdated
|
||
} | ||
|
||
&.mat-accent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to make a mixin here instead of repeating for primary/accent/warn?
src/lib/chips/chip-input.ts
Outdated
|
||
/** Register input for chip list */ | ||
@Input() | ||
set mdChipList(value: MdChipList) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This property should be just chipList
and the input should be @Input('mdChipList')
and there also needs to be a corresponding input for matChipList
src/lib/chips/chip.ts
Outdated
host: { | ||
'[class.mat-chip]': 'true', | ||
'tabindex': '-1', | ||
'role': 'option', | ||
|
||
'[class.mat-chip-selected]': 'selected', | ||
'[class.mat-chip-has-remove-icon]': '_hasRemoveIcon', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way to avoid having this class on the chip? It seems unnecessarily complicated that the chip has to know whether it contains a remove button.
src/lib/chips/chip.ts
Outdated
this._hasRemoveIcon = value; | ||
} | ||
|
||
protected _checkDisabled(event: Event): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we omit this method? It's name doesn't really tell you what it does and it's just a big side-effect
src/lib/chips/chips.scss
Outdated
} | ||
|
||
.mat-chip-list-container .mat-input-placeholder-wrapper { | ||
top: -4px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having super-specific negative absolute coordinates like this seems like a code smell to me. Is there a way to eliminate this, or to alternatively make it more explainable?
src/lib/chips/chips.scss
Outdated
top: -4px; | ||
|
||
[dir='rtl'] & { | ||
right: 8px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this 8px
a variable?
src/lib/chips/chips.scss
Outdated
display: flex; | ||
flex-direction: row; | ||
flex-wrap: wrap; | ||
align-items: flex-start; | ||
|
||
.mat-chip:not(.mat-basic-chip) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe for a follow-up PR (can add a TODO), but I'd like to get rid of all of the :not(.mat-basic-chip)
. It raises the specificity such that you can't just target .mat-chip
. Would be better to target a CSS class that is only applied when the basic chip directive isn't applied.
Comments addressed. Please take another look. Thanks! |
src/lib/chips/chip-input.ts
Outdated
} | ||
|
||
@Directive({ | ||
selector: 'input[mdChipList], input[matChipList]', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought about this some more- can we make the selector mdChipInputFor
?
When the other properties would be, e.g., mdChipInputAddOnBlur
src/lib/chips/chip-input.ts
Outdated
@Input() separatorKeysCodes: number[] = [ENTER]; | ||
|
||
/** Emitted when a chip is to be added. */ | ||
@Output('mdChipEnd') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of mdChipInputTokenEnd
? Didn't think of that yesterday, and I feel like it captures the intent pretty well
src/lib/chips/chip-input.ts
Outdated
* Defaults to `[ENTER]`. | ||
*/ | ||
// TODO(tinayuangao): Support Set here | ||
@Input() separatorKeysCodes: number[] = [ENTER]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one would be @Input('mdChipInputSeparatorKeyCodes')
src/lib/chips/chip-list.ts
Outdated
/** | ||
* Whether or not this chip is selectable. When a chip is not selectable, | ||
* it's selected state is always ignored. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove this comment?
src/lib/chips/chip-list.ts
Outdated
@@ -169,6 +212,14 @@ export class MdChipList implements AfterContentInit, OnDestroy { | |||
} | |||
|
|||
/** | |||
* Check the tab index as you should not be allowed to focus an empty list. | |||
*/ | |||
protected _checkTabIndex(): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should call this something like _updateTabIndex
("check" by itself doesn't communicate that the function changes anything)
Actually, though, this whole thing seems like it should be a host binding rather than something that is imperatively updated.
src/lib/chips/chip-list.ts
Outdated
@@ -48,23 +62,32 @@ import {Subscription} from 'rxjs/Subscription'; | |||
}) | |||
export class MdChipList implements AfterContentInit, OnDestroy { | |||
|
|||
/** When a chip is destroyed, we track the index so we can focus the appropriate next chip. */ | |||
protected _destroyedIndex: number = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about _lastDestroyedIndex
or _mostRecentDestroyedIndex
?
src/lib/chips/chip-list.ts
Outdated
focus() { | ||
// TODO: ARIA says this should focus the first `selected` chip. | ||
this._keyManager.setFirstItemActive(); | ||
// TODO: ARIA says this should focus the first `selected` chip if any are selected. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you put the TODO inside the function body? I think dgeni won't be able to connect the JsDoc to the function with this in-between.
I would also rephrase:
/**
* Focuses the the first non-disabled chip in this chip list, or the associated input when there
* are no eligible chips.
*/
src/lib/chips/chip-list.ts
Outdated
this._keyManager.onKeydown(event); | ||
} | ||
/** Attempt to focus an input if we have one. */ | ||
focusInput() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should be internal
src/lib/chips/chip-list.ts
Outdated
* Checks to see if a focus chip was recently destroyed so that we can refocus the next closest | ||
* one. | ||
*/ | ||
protected _checkDestroyedFocus() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about _updateFocusForDestroyedChips
?
src/lib/chips/chip-list.ts
Outdated
|
||
if (this._destroyedIndex != null && chipsArray.length > 0) { | ||
// Check whether the destroyed chip was the last item | ||
if (this._destroyedIndex >= chipsArray.length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if-else block could be replaced with:
const newFocusIndex = Math.min(this._destroyedIndex, chipsArray.length - 1);
this._keyManager.setActiveItem(newFocusIndex);
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored by someone other than the pull request submitter. We need to confirm that they're okay with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, there's just one lint error
Add the "merge-ready" label when that's fixed
Add events, styling and keyboard controls to allow removable chips. - Add basic styling for a user-provided remove icon. - Add keyboard controls for backspace/delete. - Add `(remove)` event which is emitted when the remove icon or one of the delete keys is pressed. - Add `md-chip-remove` directive which can be applied to `<md-icon>` (or others) to inform the chip of the remove request. Add new directive `mdChipInput` for controlling: - `(chipAdded)` - Event fired when a chip should be added. - `[separatorKeys]` - The list of keycodes that will fire the `(chipAdded)` event. - `[addOnBlur]` - Whether or not to fire the `(chipAdded)` event when the input is blurred. Additionally, fix some issues with dark theme and add styling/support for usage inside the `md-input-container` and add styling for focused chips. BREAKING CHANGE - The `selectable` property of the `md-chip-list` has now been moved to `md-chip` to maintain consistency with the new `removable` option. If you used the following code, ```html <md-chip-list [selectable]="selectable"> <md-chip>My Chip</md-chip> </md-chip-list> ``` you should switch it to ```html <md-chip-list> <md-chip [selectable]="selectable">My Chip</md-chip> </md-chip-list> ``` References angular#120. Closes angular#3143. Hat tip to @willshowell for suggestion to use secondary-text for focus color :-)
Comments addressed. Added margin for input. Please take another look. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to suggest the following css to help balance the spacing around the remove icon.
.mat-chip-remove {
margin: 0 -4px 0 4px;
}
Also the chips used to have a transparent border that turned dark when focused. It seems the last update removed that, but now when they are focused, their height increases due to added border:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also what @willshowell said about the border
src/lib/chips/chip-list.ts
Outdated
import {coerceBooleanProperty} from '@angular/cdk'; | ||
|
||
/** Utility to check if an input element has no value. */ | ||
function _isInputEmpty(element: HTMLElement): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this to the bottom of the file (we typically put module-level functions at the bottom). Also can remove the leading _
since it's scoped to this module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved _isInputEmpty
to MdChipList
.
Fixed border outline. Please take another look. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@tinayuangao @jelbourn just noticed that the |
Merging this PR now, can make other fixes in a follow-up |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Continue work of #2476