Merge branch 'card-overhaul' into deep-restructure

old
Nathan Marks 2015-11-22 23:19:54 -05:00
commit 801cdd9115
12 changed files with 325 additions and 68 deletions

View File

@ -2,6 +2,10 @@ import React, { PropTypes } from 'react';
import ClassNames from 'classnames';
import style from './style';
/**
* The base card component. This acts as the main card container
* that all subcomponents are placed within.
*/
const Card = ({
children,
className,
@ -21,8 +25,10 @@ const Card = ({
};
Card.propTypes = {
/** Child components, usually Card subcomponents. */
children: PropTypes.any,
className: PropTypes.string,
/** Increases the shadow depth to appear elevated. */
raised: PropTypes.bool
};

View File

@ -2,6 +2,12 @@ import React, { PropTypes, Component } from 'react';
import ClassNames from 'classnames';
import style from './style';
/**
* This component is used as a container for supplemental
* card actions. Supplemental actions within the card are
* explicitly called out using icons, text, and UI controls,
* typically placed at the bottom of the card.
*/
class CardActions extends Component {
static propTypes = {

View File

@ -2,17 +2,35 @@ import React, { PropTypes, Component } from 'react';
import ClassNames from 'classnames';
import style from './style';
/**
* Used for displaying media such as images or videos
* on a card. Can also be used with a solid background
* color instead of an image.
*/
class CardMedia extends Component {
static propTypes = {
/**
* Forces a 16:9 or 1:1 aspect ratio respectively. Unset, the media area will have a flexible height.
*/
aspectRatio: PropTypes.oneOf([ 'wide', 'square' ]),
children: PropTypes.node,
/**
* Usually an image/video element or a `<CardTitle>` component.
*/
children: PropTypes.any,
className: PropTypes.string,
/** Sets the background color */
color: PropTypes.string,
/**
* Creates a dark overlay underneath the child components.
*/
contentOverlay: PropTypes.bool,
/**
* Can be used instead of children. Accepts an element or a URL string.
*/
image: PropTypes.oneOfType([
PropTypes.string,
PropTypes.node
PropTypes.element
])
}

View File

@ -2,6 +2,10 @@ import React, { PropTypes, Component } from 'react';
import ClassNames from 'classnames';
import style from './style';
/**
* Basic card content container. Good for
* small descriptions or other supplementary text.
*/
class CardText extends Component {
static propTypes = {

View File

@ -3,16 +3,20 @@ import ClassNames from 'classnames';
import { Avatar } from '../avatar';
import style from './style';
const CardTitle = (props) => {
const {
avatar,
children,
className,
subtitle,
title,
...otherProps
} = props;
/**
* A versatile title block that can be used in
* various places on the card, including the media
* area. This component can also display an avatar next
* to the title content.
*/
const CardTitle = ({
avatar,
children,
className,
subtitle,
title,
...otherProps
}) => {
const classes = ClassNames(style.cardTitle, {
[style.small]: avatar,
@ -53,7 +57,8 @@ CardTitle.propTypes = {
]),
children: PropTypes.oneOfType([
PropTypes.string,
PropTypes.element
PropTypes.element,
PropTypes.array
]),
className: PropTypes.string,
subtitle: PropTypes.string,

View File

@ -22,17 +22,78 @@ const TestCards = () => (
);
```
## Properties
<!--component-docgen-start-->
| Name | Type | Default | Description|
## Card `<Card/>`
The base card component. This acts as the main card container
that all subcomponents are placed within.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `actions` | `Array` | | Array of objects describing actions. These actions will be rendered as buttons and the object fields will be transferred to those.|
| `className` | `String` | `''` | Sets a class to give customized styles to the card.|
| `color` | `String` | | Sets HEX or RGBA color to add a colored layer to the heading.|
| `image` | `String` | | URL to sets a background image in the heading.|
| `loading` | `Boolean` | `false` | If true, component will be disabled and showing a loading animation.|
| `onClick` | `Function` | | Callback function that is fired when the components's is clicked. It also will display a ripple effect on click. |
| `subtitle` | `String` | | Sets a complementary smaller text under the title.|
| `text` | `String` | | Sets a complementary text display as a card description.|
| `title` | `String` | | Sets the title of the card.|
| `type` | `String` | `default` | Type of the component to display general modifications. It can be `wide` for a larger card, `image` if it's an image card or `event` which shows just a title on top. |
| `children` | `any` | | Child components, usually Card subcomponents. |
| `className` | `string` | | Additional class(es) for custom styling. |
| `raised` | `bool` | | Increases the shadow depth to appear elevated. |
------------------------------------------------------------------
## CardActions `<CardActions/>`
This component is used as a container for supplemental
card actions. Supplemental actions within the card are
explicitly called out using icons, text, and UI controls,
typically placed at the bottom of the card.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `children` | `any` | | Children to pass through the component. |
| `className` | `string` | | Additional class(es) for custom styling. |
------------------------------------------------------------------
## CardMedia `<CardMedia/>`
Used for displaying media such as images or videos
on a card. Can also be used with a solid background
color instead of an image.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `aspectRatio` | `enum`(`'wide'`,`'square'`) | | Forces a 16:9 or 1:1 aspect ratio respectively. Unset, the media area will have a flexible height. |
| `children` | `any` | | Usually an image/video element or a `<CardTitle>` component. |
| `className` | `string` | | Additional class(es) for custom styling. |
| `color` | `string` | | Sets the background color |
| `contentOverlay` | `bool` | | Creates a dark overlay underneath the child components. |
| `image` | `union`(`string`,`element`) | | Can be used instead of children. Accepts an element or a URL string. |
------------------------------------------------------------------
## CardText `<CardText/>`
Basic card content container. Good for
small descriptions or other supplementary text.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `children` | `any` | | Children to pass through the component. |
| `className` | `string` | | Additional class(es) for custom styling. |
------------------------------------------------------------------
## CardTitle `<CardTitle/>`
A versatile title block that can be used in
various places on the card, including the media
area. This component can also display an avatar next
to the title content.
### Properties
| Name | Type | Default | Description |
|:-----|:-----|:-----|:-----|
| `avatar` | `union`(`string`,`element`) | | |
| `children` | `union`(`string`,`element`,`array`) | | Children to pass through the component. |
| `className` | `string` | | Additional class(es) for custom styling. |
| `subtitle` | `string` | | |
| `title` | `string` | | |
------------------------------------------------------------------

View File

@ -1,43 +1,37 @@
import './utils/polyfills'; // Import polyfills for IE11
import App from './app';
import AppBar from './app_bar';
import Autocomplete from './autocomplete';
import Button from './button';
import Card from './card';
import Checkbox from './checkbox';
import DatePicker from './date_picker';
import Dialog from './dialog';
import Drawer from './drawer';
import Dropdown from './dropdown';
import FontIcon from './font_icon';
import Form from './form';
import Input from './input';
import Link from './link';
import List from './list/List';
import ListItem from './list/ListItem';
import ListDivider from './list/ListDivider';
import ListCheckbox from './list/ListCheckbox';
import ListSubHeader from './list/ListSubHeader';
import Menu from './menu/Menu';
import MenuItem from './menu/MenuItem';
import MenuDivider from './menu/MenuDivider';
import IconMenu from './menu/IconMenu';
import Navigation from './navigation';
import ProgressBar from './progress_bar';
import RadioGroup from './radio/RadioGroup';
import RadioButton from './radio/RadioButton';
import Ripple from './ripple';
import Slider from './slider';
import Snackbar from './snackbar';
import Switch from './switch';
import Table from './table';
import Tabs from './tabs/Tabs';
import Tab from './tabs/Tab';
import Tooltip from './tooltip';
import TimePicker from './time_picker';
export default { App, AppBar, Autocomplete, Button, Card, Checkbox, DatePicker,
Dialog, Drawer, Dropdown, FontIcon, Form, Input, Link, List, ListItem,
ListDivider, ListCheckbox, ListSubHeader, Menu, MenuItem, MenuDivider,
IconMenu, Navigation, ProgressBar, RadioGroup, RadioButton, Ripple, Slider,
Snackbar, Switch, Table, Tabs, Tab, Tooltip, TimePicker };
export App from './app';
export AppBar from './app_bar';
export Autocomplete from './autocomplete';
export Button from './button';
export * from './card';
export Checkbox from './checkbox';
export DatePicker from './date_picker';
export Dialog from './dialog';
export Drawer from './drawer';
export Dropdown from './dropdown';
export FontIcon from './font_icon';
export Form from './form';
export Input from './input';
export Link from './link';
export List from './list/List';
export ListItem from './list/ListItem';
export ListDivider from './list/ListDivider';
export ListCheckbox from './list/ListCheckbox';
export ListSubHeader from './list/ListSubHeader';
export Menu from './menu/Menu';
export MenuItem from './menu/MenuItem';
export MenuDivider from './menu/MenuDivider';
export IconMenu from './menu/IconMenu';
export Navigation from './navigation';
export ProgressBar from './progress_bar';
export RadioGroup from './radio/RadioGroup';
export RadioButton from './radio/RadioButton';
export Ripple from './ripple';
export Slider from './slider';
export Snackbar from './snackbar';
export Switch from './switch';
export Table from './table';
export Tabs from './tabs/Tabs';
export Tab from './tabs/Tab';
export Tooltip from './tooltip';
export TimePicker from './time_picker';

View File

@ -4,7 +4,7 @@ import { Card, Button } from 'react-toolbox';
import Logo from '../../logo';
import Navigation from '../../navigation';
import style from './style';
import authors from './modules/authors';
import authors from './modules/authors.jsx';
const Home = () => (
<article>

View File

@ -2,6 +2,11 @@
@import "~react-toolbox/app_bar/config";
@import "~react-toolbox/button/config";
hr {
margin: 4rem 0;
border-top: 1px solid $color-divider;
}
.appbar {
padding-right: 8 * $unit;
}

View File

@ -56,6 +56,7 @@
"babel-eslint": "^4.1.5",
"babel-loader": "^5.3.2",
"babel-plugin-react-transform": "^1.1.1",
"bluebird": "^3.0.5",
"classnames": "^2.2.0",
"core-js": "^1.2.6",
"cpx": "^1.2.1",
@ -67,6 +68,7 @@
"expect": "^1.8.0",
"express": "^4.13.3",
"extract-text-webpack-plugin": "^0.8.2",
"glob": "^6.0.1",
"karma": "^0.13.3",
"karma-chrome-launcher": "^0.2.0",
"karma-cli": "^0.1.0",
@ -82,6 +84,7 @@
"react": "^0.14",
"react-addons-css-transition-group": "^0.14.0",
"react-addons-test-utils": "^0.14.0",
"react-docgen": "^2.4.0",
"react-dom": "^0.14.0",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.1",

89
tools/buildReadme.js Executable file
View File

@ -0,0 +1,89 @@
import Fs from 'fs';
import GenerateMarkdown from './generateMarkdown';
import Glob from 'glob';
import Path from 'path';
import { parse as ParseComponent } from 'react-docgen';
import Promise from 'bluebird';
const getComponentName = (filepath) => {
let name = Path.basename(filepath);
let ext;
while ((ext = Path.extname(name))) {
name = name.substring(0, name.length - ext.length);
}
return name;
};
const componentGlob = Path.join(process.argv[2], '/*.jsx');
new Promise((resolve, reject) => {
Glob(componentGlob, (err, files) => {
if (err) {
return reject(err);
}
return resolve(files);
});
}).then(filePaths => {
const files = {};
filePaths.forEach(path => {
files[getComponentName(path)] = new Promise((resolveRead, rejectRead) => {
Fs.readFile(path, 'utf8', (err, data) => {
if (err) {
return rejectRead(err);
}
return resolveRead(data);
});
});
});
return Promise.props(files);
}).then(fulfillments => {
for (const componentName in fulfillments) {
fulfillments[componentName] = ParseComponent(fulfillments[componentName]);
}
return fulfillments;
}).then(fulfillments => {
let markdown = '';
for (const componentName in fulfillments) {
const reactAPI = fulfillments[componentName];
markdown = markdown
.concat(GenerateMarkdown(componentName, reactAPI))
.concat('\n\n------------------------------------------------------------------\n\n');
}
return markdown;
}).then(markdown => {
return new Promise((resolve, reject) => {
Fs.readFile(Path.join(process.argv[2], '/readme.md'), 'utf8', (err, contents) => {
if (err) {
return reject(err);
}
const contentLines = contents.split('\n');
const introLines = [];
contentLines.some(line => {
introLines.push(line);
if (line === '<!--component-docgen-start-->') {
introLines.push('\n');
return true;
}
});
const newMarkdown = introLines.join('\n').concat(markdown);
return resolve(newMarkdown);
});
});
}).then(newMarkdown => {
Fs.writeFileSync(Path.join(process.argv[2], '/readme.md'), newMarkdown);
});

66
tools/generateMarkdown.js Normal file
View File

@ -0,0 +1,66 @@
function generateTitle (name) {
return `## ${name} \`<${name}/>\``;
}
function generateDesciption (description) {
return description + '\n';
}
function generatePropType (type) {
let values;
if (Array.isArray(type.value)) {
values = '(`' +
type.value.map(function (typeValue) {
return typeValue.name || typeValue.value;
}).join('`,`') +
'`)';
} else {
values = type.value;
}
return `\`${type.name}\`${(values ? values : '')}`;
}
function generateProp (propName, prop) {
if (!prop.description) {
if (propName === 'className') {
prop.description = 'Additional class(es) for custom styling.';
} else if (propName === 'children') {
prop.description = 'Children to pass through the component.';
}
}
return (
`| \`${propName}\` ${prop.required ? '(required)' : ''}` +
`| ${(prop.type ? generatePropType(prop.type) : '')} ` +
`| ${(prop.defaultValue ? `\`${prop.defaultValue}\`` : '')} ` +
`| ${(prop.description ? prop.description : '')} ` +
'|'
);
}
function generateProps (props) {
const title = '### Properties';
return (
`${title}\n` +
'| Name | Type | Default | Description |\n' +
'|:-----|:-----|:-----|:-----|\n' +
Object.keys(props).sort().map(propName => {
return generateProp(propName, props[propName]);
}).join('\n')
);
}
function generateMarkdown (name, reactAPI) {
const markdownString =
generateTitle(name) + '\n' +
(reactAPI.description ? generateDesciption(reactAPI.description) + '\n' : '\n') +
generateProps(reactAPI.props);
return markdownString;
}
module.exports = generateMarkdown;