Skip to content

Commit

Permalink
feat(chips): swap to toolbar a11y pattern
Browse files Browse the repository at this point in the history
BREAKING CHANGE: chips now follow the [aria toolbar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/examples/toolbar/). Chip sets are toolbars and chips are buttons or links. Filter chips are toggle buttons.
What to change:
- Remove `type` attribute from `<md-chip-set>` (you can mix and match chip types!)
- Remove `single-select` from `<md-chip-set>`. Use JS to control filter chips if single selection is required. Radio filter chips will come in a future update.
- Disabled chips CAN be focused with the keyboard if `always-focusable` is set.
- Filter chips no longer dispatch a `"selected"` event. Listen to `"click"` and use `event.target.selected` instead.
- ArrowUp and ArrowDown no longer navigate between chips. These are reserved for chip actions, like dropdown menu chips.

PiperOrigin-RevId: 566352830
  • Loading branch information
asyncLiz authored and copybara-github committed Sep 18, 2023
1 parent 1f31df8 commit 16bfac1
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 437 deletions.
1 change: 0 additions & 1 deletion chips/demo/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const collection =
new Knob('label', {defaultValue: '', ui: textInput()}),
new Knob('elevated', {defaultValue: false, ui: boolInput()}),
new Knob('disabled', {defaultValue: false, ui: boolInput()}),
new Knob('singleSelect', {defaultValue: false, ui: boolInput()}),
new Knob('scrolling', {defaultValue: false, ui: boolInput()}),
]);

Expand Down
105 changes: 40 additions & 65 deletions chips/demo/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export interface StoryKnobs {
label: string;
elevated: boolean;
disabled: boolean;
singleSelect: boolean;
scrolling: boolean;
}

Expand All @@ -44,14 +43,13 @@ const styles = css`
}
`;

const standard: MaterialStoryInit<StoryKnobs> = {
const assist: MaterialStoryInit<StoryKnobs> = {
name: 'Assist chips',
styles,
render({label, elevated, disabled, scrolling}) {
const classes = {scrolling};
const classes = {'scrolling': scrolling};
return html`
<md-chip-set type="assist" class=${classMap(classes)}
aria-label="Assist chips">
<md-chip-set class=${classMap(classes)} aria-label="Assist chips">
<md-assist-chip
label=${label || 'Assist chip'}
?disabled=${disabled}
Expand All @@ -64,26 +62,18 @@ const standard: MaterialStoryInit<StoryKnobs> = {
>
<md-icon slot="icon">local_laundry_service</md-icon>
</md-assist-chip>
</md-chip-set>
`;
}
};

const links: MaterialStoryInit<StoryKnobs> = {
name: 'Assist link chips',
styles,
render({label, elevated, disabled, scrolling}) {
const classes = {scrolling};
return html`
<md-chip-set type="assist" class=${classMap(classes)}
aria-label="Assist link chips">
<md-assist-chip
label=${label || 'Assist link chip'}
?disabled=${disabled}
?elevated=${elevated}
href="https://google.com"
target="_blank"
>${GOOGLE_LOGO}</md-assist-chip>
<md-assist-chip
label=${label || 'Disabled assist chip (focusable)'}
disabled
always-focusable
?elevated=${elevated}
></md-assist-chip>
</md-chip-set>
`;
}
Expand All @@ -92,12 +82,11 @@ const links: MaterialStoryInit<StoryKnobs> = {
const filters: MaterialStoryInit<StoryKnobs> = {
name: 'Filter chips',
styles,
render({label, elevated, disabled, scrolling, singleSelect}) {
const classes = {scrolling};
render({label, elevated, disabled, scrolling}) {
const classes = {'scrolling': scrolling};
return html`
<md-chip-set type="filter" class=${classMap(classes)}
aria-label="Filter chips"
?single-select=${singleSelect}>
<md-chip-set class=${classMap(classes)}
aria-label="Filter chips">
<md-filter-chip
label=${label || 'Filter chip'}
?disabled=${disabled}
Expand All @@ -116,6 +105,13 @@ const filters: MaterialStoryInit<StoryKnobs> = {
?elevated=${elevated}
removable
></md-filter-chip>
<md-filter-chip
label=${label || 'Disabled filter chip (focusable)'}
disabled
always-focusable
?elevated=${elevated}
removable
></md-filter-chip>
</md-chip-set>
`;
}
Expand All @@ -125,10 +121,9 @@ const inputs: MaterialStoryInit<StoryKnobs> = {
name: 'Input chips',
styles,
render({label, disabled, scrolling}) {
const classes = {scrolling};
const classes = {'scrolling': scrolling};
return html`
<md-chip-set type="input" class=${classMap(classes)}
aria-label="Input chips">
<md-chip-set class=${classMap(classes)} aria-label="Input chips">
<md-input-chip
label=${label || 'Input chip'}
?disabled=${disabled}
Expand All @@ -146,30 +141,21 @@ const inputs: MaterialStoryInit<StoryKnobs> = {
>
<img slot="icon" src="https://lh3.googleusercontent.com/a/default-user=s48">
</md-input-chip>
<md-input-chip
label=${label || 'Input link chip'}
href="https://google.com"
target="_blank"
>${GOOGLE_LOGO}</md-input-chip>
<md-input-chip
label=${label || 'Remove-only input chip'}
?disabled=${disabled}
remove-only
></md-input-chip>
</md-chip-set>
`;
}
};

const inputLinks: MaterialStoryInit<StoryKnobs> = {
name: 'Input link chips',
styles,
render({label, disabled, scrolling}) {
const classes = {scrolling};
return html`
<md-chip-set type="input" class=${classMap(classes)}
aria-label="Input link chips">
<md-input-chip
label=${label || 'Input link chip'}
?disabled=${disabled}
href="https://google.com"
target="_blank"
>${GOOGLE_LOGO}</md-input-chip>
label=${label || 'Disabled input chip (focusable)'}
disabled
always-focusable
></md-input-chip>
</md-chip-set>
`;
}
Expand All @@ -179,10 +165,9 @@ const suggestions: MaterialStoryInit<StoryKnobs> = {
name: 'Suggestion chips',
styles,
render({label, elevated, disabled, scrolling}) {
const classes = {scrolling};
const classes = {'scrolling': scrolling};
return html`
<md-chip-set type="suggestion" class=${classMap(classes)}
aria-label="Suggestion chips">
<md-chip-set class=${classMap(classes)} aria-label="Suggestion chips">
<md-suggestion-chip
label=${label || 'Suggestion chip'}
?disabled=${disabled}
Expand All @@ -195,32 +180,22 @@ const suggestions: MaterialStoryInit<StoryKnobs> = {
>
<md-icon slot="icon">local_laundry_service</md-icon>
</md-suggestion-chip>
</md-chip-set>
`;
}
};

const suggestionLinks: MaterialStoryInit<StoryKnobs> = {
name: 'Suggestion link chips',
styles,
render({label, elevated, disabled, scrolling}) {
const classes = {scrolling};
return html`
<md-chip-set type="suggestion" class=${classMap(classes)}
aria-label="Suggestion link chips">
<md-suggestion-chip
label=${label || 'Suggestion link chip'}
?disabled=${disabled}
?elevated=${elevated}
href="https://google.com"
target="_blank"
>${GOOGLE_LOGO}</md-suggestion-chip>
<md-suggestion-chip
label=${label || 'Disabled suggestion chip (focusable)'}
disabled
always-focusable
?elevated=${elevated}
></md-suggestion-chip>
</md-chip-set>
`;
}
};

/** Chips stories. */
export const stories = [
standard, links, filters, inputs, inputLinks, suggestions, suggestionLinks
];
export const stories = [assist, filters, inputs, suggestions];
6 changes: 0 additions & 6 deletions chips/internal/_chip-set.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,4 @@
flex-wrap: wrap;
gap: 8px;
}

.content {
display: flex;
flex-wrap: inherit;
gap: inherit;
}
}
16 changes: 6 additions & 10 deletions chips/internal/assist-chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {property} from 'lit/decorators.js';

import {ARIAMixinStrict} from '../../internal/aria/aria.js';

import {Chip, renderGridAction, renderGridContainer} from './chip.js';
import {Chip} from './chip.js';

/**
* An assist chip component.
Expand All @@ -30,10 +30,6 @@ export class AssistChip extends Chip {
return !this.href && this.disabled;
}

protected override renderContainer(content: unknown) {
return renderGridContainer(content, this.getContainerClasses());
}

protected override getContainerClasses() {
return {
...super.getContainerClasses(),
Expand All @@ -47,24 +43,24 @@ export class AssistChip extends Chip {
protected override renderPrimaryAction(content: unknown) {
const {ariaLabel} = this as ARIAMixinStrict;
if (this.href) {
return renderGridAction(html`
return html`
<a class="primary action"
id="link"
aria-label=${ariaLabel || nothing}
href=${this.href}
target=${this.target || nothing}
>${content}</a>
`);
`;
}

return renderGridAction(html`
return html`
<button class="primary action"
id="button"
aria-label=${ariaLabel || nothing}
?disabled=${this.disabled}
?disabled=${this.disabled && !this.alwaysFocusable}
type="button"
>${content}</button>
`);
`;
}

protected override renderOutline() {
Expand Down
Loading

0 comments on commit 16bfac1

Please sign in to comment.