Skip to content
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

Merged
merged 11 commits into from
Jul 14, 2017

Conversation

tinayuangao
Copy link
Contributor

Continue work of #2476

@googlebot googlebot added the cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla label Jun 1, 2017
@tinayuangao tinayuangao force-pushed the chips branch 2 times, most recently from 33174bb to 03d293e Compare June 1, 2017 21:31
@tinayuangao tinayuangao requested review from mmalerba and jelbourn June 1, 2017 23:36
@tinayuangao tinayuangao added pr: needs review and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla labels Jun 2, 2017
@tinayuangao tinayuangao removed the request for review from jelbourn June 2, 2017 18:08
@jelbourn jelbourn changed the title feat(chips): Add remove functionality/styling. feat(chips): Add removal functionality/styling. Jun 2, 2017
@jelbourn jelbourn added the cla: yes PR author has agreed to Google's Contributor License Agreement label Jun 2, 2017
Copy link
Member

@jelbourn jelbourn left a 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

@@ -39,13 +46,29 @@ export class ChipsDemo {
alert(message);
Copy link
Member

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?

<md-input-container>
<input mdInput #input (keyup.enter)="add(input)" placeholder="New Contributor..."/>
<md-input-container mdChipListContainer>
<md-chip-list mdPrefix #chipList>
Copy link
Member

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?

let value = event.value;

// Add our person
if (value && value.trim() != '') {
Copy link
Member

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())


}

&.mat-accent {
Copy link
Member

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?


/** Register input for chip list */
@Input()
set mdChipList(value: MdChipList) {
Copy link
Member

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

host: {
'[class.mat-chip]': 'true',
'tabindex': '-1',
'role': 'option',

'[class.mat-chip-selected]': 'selected',
'[class.mat-chip-has-remove-icon]': '_hasRemoveIcon',
Copy link
Member

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.

this._hasRemoveIcon = value;
}

protected _checkDisabled(event: Event): boolean {
Copy link
Member

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

}

.mat-chip-list-container .mat-input-placeholder-wrapper {
top: -4px;
Copy link
Member

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?

top: -4px;

[dir='rtl'] & {
right: 8px;
Copy link
Member

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?

display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;

.mat-chip:not(.mat-basic-chip) {
Copy link
Member

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.

@googlebot googlebot added cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla and removed cla: yes PR author has agreed to Google's Contributor License Agreement labels Jun 5, 2017
@tinayuangao
Copy link
Contributor Author

Comments addressed. Please take another look. Thanks!

@tinayuangao tinayuangao added cla: yes PR author has agreed to Google's Contributor License Agreement and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla labels Jun 5, 2017
}

@Directive({
selector: 'input[mdChipList], input[matChipList]',
Copy link
Member

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

@Input() separatorKeysCodes: number[] = [ENTER];

/** Emitted when a chip is to be added. */
@Output('mdChipEnd')
Copy link
Member

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

* Defaults to `[ENTER]`.
*/
// TODO(tinayuangao): Support Set here
@Input() separatorKeysCodes: number[] = [ENTER];
Copy link
Member

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')

/**
* Whether or not this chip is selectable. When a chip is not selectable,
* it's selected state is always ignored.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this comment?

@@ -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 {
Copy link
Member

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.

@@ -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;
Copy link
Member

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?

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.
Copy link
Member

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.
   */

this._keyManager.onKeydown(event);
}
/** Attempt to focus an input if we have one. */
focusInput() {
Copy link
Member

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

* Checks to see if a focus chip was recently destroyed so that we can refocus the next closest
* one.
*/
protected _checkDestroyedFocus() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about _updateFocusForDestroyedChips?


if (this._destroyedIndex != null && chipsArray.length > 0) {
// Check whether the destroyed chip was the last item
if (this._destroyedIndex >= chipsArray.length) {
Copy link
Member

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);

@googlebot
Copy link

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 cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.

@googlebot googlebot added cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla and removed cla: yes PR author has agreed to Google's Contributor License Agreement labels Jun 6, 2017
@tinayuangao tinayuangao added cla: yes PR author has agreed to Google's Contributor License Agreement and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla labels Jun 6, 2017
Copy link
Member

@jelbourn jelbourn left a 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

@googlebot googlebot added cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla and removed cla: yes PR author has agreed to Google's Contributor License Agreement labels Jun 6, 2017
topherfangio and others added 9 commits July 12, 2017 10:25
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 :-)
@googlebot googlebot added cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla and removed cla: yes PR author has agreed to Google's Contributor License Agreement labels Jul 12, 2017
@tinayuangao
Copy link
Contributor Author

Comments addressed. Added margin for input. Please take another look. Thanks!

Copy link
Contributor

@willshowell willshowell left a 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:

screen shot 2017-07-12 at 3 01 16 pm

Copy link
Member

@jelbourn jelbourn left a 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

import {coerceBooleanProperty} from '@angular/cdk';

/** Utility to check if an input element has no value. */
function _isInputEmpty(element: HTMLElement): boolean {
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved _isInputEmpty to MdChipList.

@tinayuangao
Copy link
Contributor Author

Fixed border outline. Please take another look. Thanks!

Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jelbourn jelbourn added action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla pr: needs review labels Jul 12, 2017
@willshowell
Copy link
Contributor

@tinayuangao @jelbourn just noticed that the .mat-chip-remove.mat-icon styles are in the demo stylesheet rather than chips.scss. Should it be up to the consumer to set the font-size/height/width/alignment of the icon?

@jelbourn
Copy link
Member

Merging this PR now, can make other fixes in a follow-up

@jelbourn jelbourn merged commit c82aca9 into angular:master Jul 14, 2017
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker cla: yes PR author has agreed to Google's Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants