Skip to content

Commit

Permalink
[Chip] Migrate component
Browse files Browse the repository at this point in the history
[Avatar] Support children, change default colors
  • Loading branch information
mbrookes committed Jan 11, 2017
1 parent 5d11633 commit 943f95f
Show file tree
Hide file tree
Showing 25 changed files with 737 additions and 64 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ node_modules
/packages/**/lib
/packages/icon-builder
/packages/material-ui-codemod/modules/v0.15.0
/src/svg-icons
/test/coverage
/test/regressions/
/test/integration/
4 changes: 2 additions & 2 deletions docs/api/Avatar/Avatar.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Props
| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| alt | string | '' | Used in combination with `src` or `srcSet` to provide an alt attribute for the rendered `img` element. |
| children | node | | Used to render icon or text elements inside the Avatar. `src` and `alt` props will not be used and no `img` will be rendered by default.<br>This can be an element, or just a string. |
| className | string | | The CSS class name of the root element. |
| component | string | 'div' | |
| icon | node | | Supply a custom icon. `src` and `alt` props will not be used and no `img` will be renderd by default.<br>This can be a custom element, or even just a string. |
| component | string | 'div' | The component type of the root element. |
| sizes | string | | sizes desc |
| src | string | | src desc |
| srcSet | string | | srcSet desc |
Expand Down
23 changes: 23 additions & 0 deletions docs/api/Chip/Chip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Chip
====

Chips represent complex entities in small blocks, such as a contact.

```jsx
<Chip avatar={<Avatar>} label="Label text" />
```

Props
-----

| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| avatar | node | | Avatar element. |
| className | string | | CSS `className` of the root element. |
| deleteIconClassName | string | | CSS `className` of the delete icon element. |
| label | string | | Label |
| labelClassName | string | | CSS `className` of the label. |
| onClick | function | | Callback function fired when the `Chip` element is clicked. If set, the chip will by styled for hover focus and active states.<br><br>**Signature:**<br>`function(event: object) => void`<br>*event:* `onClick` event targeting the root element. |
| onRequestDelete | function | | Callback function fired when the delete icon is clicked. If set, the delete icon will be shown.<br><br>**Signature:**<br>`function(event: object) => void`<br>*event:* `onClick` event targeting the delete icon element. |

Any other properties supplied will be spread to the root element.
Binary file added docs/site/assets/images/uxceo-128.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 9 additions & 12 deletions docs/site/src/demos/avatars/IconAvatars.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,15 @@ export default function IconAvatars(props, context) {
const classes = context.styleManager.render(styleSheet);
return (
<div className={classes.row}>
<Avatar
icon={<FolderIcon />}
className={classes.avatar}
/>
<Avatar
icon={<PageviewIcon />}
className={classes.pinkAvatar}
/>
<Avatar
icon={<AssignmentIcon />}
className={classes.greenAvatar}
/>
<Avatar className={classes.avatar}>
<FolderIcon />
</Avatar>
<Avatar className={classes.pinkAvatar}>
<PageviewIcon />
</Avatar>
<Avatar className={classes.greenAvatar}>
<AssignmentIcon />
</Avatar>
</div>
);
}
Expand Down
15 changes: 3 additions & 12 deletions docs/site/src/demos/avatars/LetterAvatars.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,9 @@ export default function LetterAvatars(props, context) {
const classes = context.styleManager.render(styleSheet);
return (
<div className={classes.row}>
<Avatar
icon="H"
className={classes.avatar}
/>
<Avatar
icon="N"
className={classes.orangeAvatar}
/>
<Avatar
icon="O"
className={classes.purpleAvatar}
/>
<Avatar className={classes.avatar}>H</Avatar>
<Avatar className={classes.orangeAvatar}>N</Avatar>
<Avatar className={classes.purpleAvatar}>OP</Avatar>
</div>
);
}
Expand Down
4 changes: 2 additions & 2 deletions docs/site/src/demos/avatars/avatars.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ Image avatars can be created by passing standard `img` props `src` or `srcSet` i

## Icon avatars

Icon avatars are created by passing an icon prop.
Icon avatars are created by passing an icon as `children`.

{{demo='demos/avatars/IconAvatars.js'}}

## Letter avatars

Avatars containing simple characters can be created by passing your string as the `icon` prop.
Avatars containing simple characters can be created by passing your string as `children`.

{{demo='demos/avatars/LetterAvatars.js'}}
65 changes: 65 additions & 0 deletions docs/site/src/demos/chips/Chips.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// @flow weak

import React, { PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Avatar from 'material-ui/Avatar';
import Chip from 'material-ui/Chip';
import Face from 'material-ui/svg-icons/face';
import { grey } from 'material-ui/styles/colors';
import avatarImage from 'docs/site/assets/images/uxceo-128.jpg';

const styleSheet = createStyleSheet('Chips', () => ({
chip: {
margin: '0 8px',
},
svgIcon: {
color: grey[800],
},
row: {
display: 'flex',
justifyContent: 'center',
},
}));

function handleRequestDelete() {
alert('You clicked the delete icon.'); // eslint-ignore-line no-alert
}

function handleClick() {
alert('You clicked the Chip.'); // eslint-ignore-line no-alert
}

export default function Chips(props, context) {
const classes = context.styleManager.render(styleSheet);
return (
<div className={classes.row}>
<Chip
label="Basic Chip"
className={classes.chip}
/>
<Chip
avatar={<Avatar>MB</Avatar>}
label="Clickable Chip"
onClick={handleClick}
className={classes.chip}
/>
<Chip
avatar={<Avatar src={avatarImage} />}
label="Deletable Chip"
onRequestDelete={handleRequestDelete}
className={classes.chip}
/>
<Chip
avatar={<Avatar><Face className={classes.svgIcon} /></Avatar>}
label="Clickable Deletable Chip"
onClick={handleClick}
onRequestDelete={handleRequestDelete}
className={classes.chip}
/>
</div>
);
}

Chips.contextTypes = {
styleManager: PropTypes.object.isRequired,
};
73 changes: 73 additions & 0 deletions docs/site/src/demos/chips/ChipsArray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @flow weak

import React, { Component, PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Chip from 'material-ui/Chip';


const styleSheet = createStyleSheet('ChipsArray', () => ({
chip: {
margin: '0 4px',
},
row: {
display: 'flex',
justifyContent: 'center',
},
}));

export default class ChipsArray extends Component {
static contextTypes = {
styleManager: PropTypes.object.isRequired,
};

state = { chipData: [
{ key: 0, label: 'Angular' },
{ key: 1, label: 'JQuery' },
{ key: 2, label: 'Polymer' },
{ key: 3, label: 'ReactJS' },
{ key: 4, label: 'Vue.js' },
] };

styles = {
chip: {
margin: 4,
},
wrapper: {
display: 'flex',
flexWrap: 'wrap',
},
};

handleRequestDelete = (key) => {
if (key === 3) {
alert('Why would you want to delete React?! :)'); // eslint-ignore-line no-alert
return;
}

const chipData = [...this.state.chipData];
const chipToDelete = chipData.indexOf(chipData.find((chip) => chip.key === key));
chipData.splice(chipToDelete, 1);
this.setState({ chipData });
};

render() {
const classes = this.context.styleManager.render(styleSheet);

const renderChip = (data) => {
return (
<Chip
label={data.label}
key={data.key}
onRequestDelete={() => this.handleRequestDelete(data.key)}
className={classes.chip}
/>
);
};

return (
<div className={classes.row}>
{this.state.chipData.map(renderChip, this)}
</div>
);
}
}
28 changes: 28 additions & 0 deletions docs/site/src/demos/chips/chips.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Chips

[Chips](https://www.google.com/design/spec/components/chips.html)
represent complex entities in small blocks, such as a contact.

While included here as a standalone component, the most common use will
be in some form of input, so some of the behaviour demonstrated here is
not shown in context.

## Chip

Examples of Chips, using an image Avatar, SVG Icon Avatar, "Letter"
and (string) Avatar.
Chips with the `onClick` property defined change appearance on focus,
hover, and click.

Chips with the `onRequestDelete` property defined will display a delete
icon which changes appearance on hover.

{{demo='demos/chips/Chips.js'}}

## Chip array
An example of rendering multiple Chips from an array of values.
Deleting a chip removes it from the array. Note that since no
`onClick` property is defined, the Chip can be focused, but does not
gain depth while clicked or touched.

{{demo='demos/chips/ChipsArray.js'}}
4 changes: 2 additions & 2 deletions docs/site/src/demos/lists/FolderList.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ function FolderList(props, context) {
<div className={classes.root}>
<List>
<ListItem button>
<Avatar icon={<FolderIcon />} />
<Avatar><FolderIcon /></Avatar>
<ListItemText primary="Photos" secondary="Jan 9, 2016" />
</ListItem>
<ListItem button>
<Avatar icon={<FolderIcon />} />
<Avatar><FolderIcon /></Avatar>
<ListItemText primary="Work" secondary="Jan 7, 2016" />
</ListItem>
</List>
Expand Down
45 changes: 31 additions & 14 deletions src/Avatar/Avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React, { PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import classNames from 'classnames';
import { emphasize } from '../styles/colorManipulator';

export const styleSheet = createStyleSheet('Avatar', (theme) => {
const { palette } = theme;
Expand All @@ -14,13 +15,14 @@ export const styleSheet = createStyleSheet('Avatar', (theme) => {
justifyContent: 'center',
width: 40,
height: 40,
fontSize: 24,
fontSize: 20,
borderRadius: '50%',
overflow: 'hidden',
userSelect: 'none',
},
defaultColor: {
color: palette.getContrastText(palette.text.disabled),
background: palette.text.disabled,
color: palette.background.default,
backgroundColor: emphasize(palette.background.default, 0.26),
},
img: {
maxWidth: '100%',
Expand All @@ -34,8 +36,9 @@ export default function Avatar(props, context) {
const {
alt,
className: classNameProp,
children: childrenProp,
childrenClassName: childrenClassNameProp,
component,
icon,
sizes,
src,
srcSet,
Expand All @@ -44,18 +47,22 @@ export default function Avatar(props, context) {

const classes = context.styleManager.render(styleSheet);
const className = classNames(classes.root, {
[classes.defaultColor]: icon && !src && !srcSet,
[classes.defaultColor]: childrenProp && !src && !srcSet,
}, classNameProp);

const containerProps = {
className,
...other,
};

let children = null;

if (icon) {
children = icon;
if (childrenProp) {
if (childrenClassNameProp && React.isValidElement(childrenProp)) {
const childrenClassName = classNames(childrenClassNameProp, childrenProp.props.className);
children = React.cloneElement(childrenProp, { className: childrenClassName });
} else {
children = childrenProp;
}
} else if (src || srcSet) {
const imgProps = {
alt,
Expand All @@ -76,18 +83,28 @@ Avatar.propTypes = {
* provide an alt attribute for the rendered `img` element.
*/
alt: PropTypes.string,
/**
* Used to render icon or text elements inside the Avatar.
* `src` and `alt` props will not be used and no `img` will
* be rendered by default.
*
* This can be an element, or just a string.
*/
children: PropTypes.node,
/**
* @ignore
* The className of the child element.
* Used by Chip to style the Avatar icon.
*/
childrenClassName: PropTypes.string,
/**
* The CSS class name of the root element.
*/
className: PropTypes.string,
component: PropTypes.string,
/**
* Supply a custom icon. `src` and `alt` props will
* not be used and no `img` will be renderd by default.
*
* This can be a custom element, or even just a string.
* The component type of the root element.
*/
icon: PropTypes.node,
component: PropTypes.string,
/**
* sizes desc
*/
Expand Down
Loading

0 comments on commit 943f95f

Please sign in to comment.