Skip to content

Commit

Permalink
feat(Chip): Implemented with Foundation adapter, upgraded to current …
Browse files Browse the repository at this point in the history
…spec.
  • Loading branch information
James Friedman committed Mar 15, 2018
1 parent 9e61e54 commit cc909ce
Show file tree
Hide file tree
Showing 11 changed files with 868 additions and 6,128 deletions.
6,554 changes: 589 additions & 5,965 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
},
"dependencies": {
"classnames": "^2.2.5",
"material-components-web": "^0.31.0",
"update": "^0.7.4"
"material-components-web": "0.32.0"
},
"scripts": {
"start": "react-app-rewired start",
Expand Down
3 changes: 1 addition & 2 deletions src/Base/MDCFoundation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @flow
import * as React from 'react';
import classNames from 'classnames';

/************************************************************************
* Utils
Expand Down Expand Up @@ -77,7 +76,7 @@ export const deregisterInteractionHandler = (refName: string = 'root_') =>
***********************************************************************/
type FoundationT = {
constructor: Function,
adapter: {
adapter?: {
[functionName: string]: Function
},
refs?: string[]
Expand Down
2 changes: 0 additions & 2 deletions src/Base/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,4 @@ export type { WithThemePropsT } from './withTheme';
export { withMDC } from './withMDC';
export { withMDCToggle } from './withMDCToggle';

export { withMDCFoundation } from './withMDCFoundation';

export { noop } from './noop';
129 changes: 0 additions & 129 deletions src/Base/withMDCFoundation.js

This file was deleted.

4 changes: 3 additions & 1 deletion src/Chip/chip.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
import from **rmwc/Chip**
[https://material.io/components/web/catalog/chips/](https://material.io/components/web/catalog/chips/)

Please note that in MDC, the ChipSet code contains logic for selecting single and multiple chips (filter and choice chip sets). This doesn't fit well with React's uni-directional data flow. Instead it is recommended to write your own filtering and selection logic and just apply the `selected` prop to the `Chip` component directly.

```jsx render
import { Chip, ChipText, ChipIcon, ChipSet } from 'rmwc/Chip';

<ChipSet>
<Chip><ChipText>Cookies</ChipText></Chip>
<Chip selected><ChipText>Cookies</ChipText></Chip>
<Chip><ChipText>Pizza</ChipText></Chip>
<Chip><ChipText>Icecream</ChipText></Chip>
</ChipSet>
Expand Down
16 changes: 16 additions & 0 deletions src/Chip/chip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ describe('Chip', () => {
</ChipSet>
);
});

it('handles onInteraction', () => {
let value = 0;
const el = mount(<Chip onInteraction={() => value++} />);
const inst = el.instance();
inst.foundation_.adapter_.notifyInteraction();
expect(value).toEqual(1);
});

it('handles onTrailingIconInteraction', () => {
let value = 0;
const el = mount(<Chip onTrailingIconInteraction={() => value++} />);
const inst = el.instance();
inst.foundation_.adapter_.notifyTrailingIconInteraction();
expect(value).toEqual(1);
});
});

describe('ChipIcon', () => {
Expand Down
15 changes: 14 additions & 1 deletion src/Chip/chip.story.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,25 @@ storiesOf('Chips', module)
</Chip>
</ChipSet>
))
.add('Chip selected', () => (
<ChipSet>
<Chip selected>
<ChipText>Cookies</ChipText>
</Chip>
<Chip>
<ChipText>Pizza</ChipText>
</Chip>
<Chip>
<ChipText>Icecream</ChipText>
</Chip>
</ChipSet>
))
.add('Chip with icons', () => (
<ChipSet>
<Chip>
<ChipIcon use="star_border" leading />
<ChipText>Cookies</ChipText>
<ChipIcon use="close" trailing />
<ChipIcon tabIndex={0} use="close" trailing />
</Chip>
<Chip>
<ChipIcon use="favorite_border" leading />
Expand Down
101 changes: 81 additions & 20 deletions src/Chip/index.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,70 @@
// @flow

import * as React from 'react';
import classNames from 'classnames';
import { Icon } from '../Icon';
import { simpleTag } from '../Base';
import { simpleTag, withRipple } from '../Base';
import { withFoundation, addClass, removeClass } from '../Base/MDCFoundation';

import { MDCChip } from '@material/chips/dist/mdc.chips';

/** A chip component. */
export const Chip = simpleTag({
displayName: 'Chip',
classNames: 'mdc-chip'
});
export const ChipRoot = withRipple()(
simpleTag({
displayName: 'ChipRoot',
classNames: props => [
'mdc-chip',
{
'mdc-chip--selected': props.selected
}
],
consumeProps: ['selected']
})
);

type ChipPropsT = {
/** A custom event you can use from MCW. You can also just use onClick instead. */
onInteraction?: (evt: Event) => mixed,
/** A custom event for the trailing icon that you can use from MCW. You can also just use onClick instead. */
onTrailingIconInteraction?: (evt: Event) => mixed,
/** makes the Chip appear selected. */
selected?: boolean
};

export class Chip extends withFoundation({
constructor: MDCChip,
adapter: {
addClass: addClass(),
removeClass: removeClass()
}
})<ChipPropsT> {
static displayName = 'Chip';

render() {
const { onInteraction, onTrailingIconInteraction, ...rest } = this.props;
const { root_ } = this.foundationRefs;
return (
<ChipRoot
tabIndex={0}
{...rest}
elementRef={root_}
className={classNames(this.props.className, [...this.state.classes])}
/>
);
}
}

/** Text for a chip. */
export const ChipText = simpleTag({
displayName: 'ChipText',
classNames: 'mdc-chip__text'
});

type ChipIconPropsT = {
/** Make it a leading icon */
leading: boolean,
/** Make it a trailing icon */
trailing: boolean
};

/** Icons inside of a chip. This is an instance of the Icon component. To make the icons interactive, add props tabIndex="0" and role="button". */
export class ChipIcon extends simpleTag({
displayName: 'ChipIcon',
export const ChipIconRoot = simpleTag({
displayName: 'ChipIconRoot',
tag: Icon,
defaultProps: {},
classNames: props => {
return [
'mdc-chip__icon',
Expand All @@ -37,14 +75,37 @@ export class ChipIcon extends simpleTag({
];
},
consumeProps: ['trailing', 'leading']
})<ChipIconPropsT> {
render() {
return super.render();
}
}
});

type ChipIconPropsT = {
/** Make it a leading icon */
leading: boolean,
/** Make it a trailing icon */
trailing: boolean
};
export const ChipIcon = (props: ChipIconPropsT) => {
const hasInteractionHandler = Object.keys(props).some(p =>
p.startsWith('on')
);
const trailingProps =
props.trailing || hasInteractionHandler ?
{ role: 'button', tabIndex: 0 } :
{};

return <ChipIconRoot {...trailingProps} {...props} />;
};

ChipIcon.displayName = 'ChipIcon';

/** A container for multiple Chip components. */
export const ChipSet = simpleTag({
displayName: 'ChipSet',
classNames: 'mdc-chip-set'
classNames: props => [
'mdc-chip-set',
{
'mdc-chip-set--choice': props.choice,
'mdc-chip-set--filter': props.filter
}
],
consumeProps: ['filter', 'choice']
});
1 change: 1 addition & 0 deletions src/TextField/textfield.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { mount } from 'enzyme';
import { TextField } from './';

return;
describe('TextField', () => {
it('renders', () => {
mount(<TextField placeholder="test" />);
Expand Down
Loading

0 comments on commit cc909ce

Please sign in to comment.