diff --git a/src/elements/Content/Content.js b/src/elements/Content/Content.js
new file mode 100644
index 0000000000..c96515be64
--- /dev/null
+++ b/src/elements/Content/Content.js
@@ -0,0 +1,33 @@
+import React, { PropTypes } from 'react'
+import cx from 'classnames'
+import META from '../../utils/Meta'
+
+function Content(props) {
+ const {
+ children, className, ...rest,
+ } = props
+
+ const classes = cx(
+ 'content',
+ className
+ )
+
+ return (
+ {children}
+ )
+}
+
+Content._meta = {
+ name: 'Content',
+ type: META.type.element,
+}
+
+Content.propTypes = {
+ /** Primary content of the List */
+ children: PropTypes.node,
+
+ /** Classes to add to the list className. */
+ className: PropTypes.string,
+}
+
+export default Content
diff --git a/src/elements/Description/Description.js b/src/elements/Description/Description.js
new file mode 100644
index 0000000000..bd1b307e3f
--- /dev/null
+++ b/src/elements/Description/Description.js
@@ -0,0 +1,34 @@
+import React, { PropTypes } from 'react'
+import cx from 'classnames'
+import META from '../../utils/Meta'
+
+function Description(props) {
+ const {
+ children, className, ...rest,
+ } = props
+
+ const classes = cx(
+ 'description',
+ className
+ )
+
+ return (
+ {children}
+ )
+}
+
+Description._meta = {
+ library: META.library.semanticUI,
+ name: 'Description',
+ type: META.type.element,
+}
+
+Description.propTypes = {
+ /** Primary content of the List */
+ children: PropTypes.node,
+
+ /** Classes to add to the list className. */
+ className: PropTypes.string,
+}
+
+export default Description
diff --git a/src/elements/Icon/Icon.js b/src/elements/Icon/Icon.js
index 93bb7f61cf..e3b7c024da 100644
--- a/src/elements/Icon/Icon.js
+++ b/src/elements/Icon/Icon.js
@@ -16,8 +16,8 @@ export default class Icon extends Component {
render() {
const { className } = this.props
const classes = cx(
- className,
'icon',
+ className
)
return (
diff --git a/src/elements/List/ItemHeader.js b/src/elements/List/ItemHeader.js
new file mode 100644
index 0000000000..a57e23f55d
--- /dev/null
+++ b/src/elements/List/ItemHeader.js
@@ -0,0 +1,38 @@
+import React, { PropTypes } from 'react'
+import cx from 'classnames'
+import META from '../../utils/Meta'
+
+/**
+ * I'm not sure a seperate file is necessary or if there's a better way.
+ * Also not sure this is where this file would go.
+ */
+
+function ItemHeader(props) {
+ const {
+ children, className, ...rest,
+ } = props
+
+ const classes = cx(
+ 'header',
+ className
+ )
+
+ return (
+ {children}
+ )
+}
+
+ItemHeader._meta = {
+ name: 'ItemHeader',
+ type: META.type.element,
+}
+
+ItemHeader.propTypes = {
+ /** Primary content of the List */
+ children: PropTypes.node,
+
+ /** Classes to add to the list className. */
+ className: PropTypes.string,
+}
+
+export default ItemHeader
diff --git a/src/elements/List/List.js b/src/elements/List/List.js
index 4ded1341ea..a8e45cfa0c 100644
--- a/src/elements/List/List.js
+++ b/src/elements/List/List.js
@@ -1,32 +1,116 @@
-import React, { Component, PropTypes } from 'react'
-import classNames from 'classnames'
+import cx from 'classnames'
+import React, { PropTypes } from 'react'
import META from '../../utils/Meta'
+import * as sui from '../../utils/semanticUtils'
+import {
+ getUnhandledProps,
+ useValueAndKey,
+ useKeyOrValueAndKey,
+ useKeyOnly,
+} from '../../utils/propUtils'
import ListItem from './ListItem'
+import Icon from '../Icon/Icon'
+import Image from '../Image/Image'
+import ItemHeader from './ItemHeader'
+import Content from '../Content/Content'
+import Description from '../Description/Description'
-export default class List extends Component {
- static propTypes = {
- children: PropTypes.node,
- className: PropTypes.string,
- }
-
- static _meta = {
- library: META.library.semanticUI,
- name: 'List',
- type: META.type.element,
- }
-
- static Item = ListItem
-
- render() {
- const classes = classNames(
- 'ui',
- this.props.className,
- 'list'
- )
- return (
-
- {this.props.children}
-
- )
- }
+function List(props) {
+ const {
+ size, aligned, bulleted, link, ordered, animated, celled, divided,
+ horizontal, inverted, relaxed, selection, children, className,
+ } = props
+
+ const classes = cx(
+ 'ui',
+ size,
+ useValueAndKey(aligned, 'aligned'),
+ useKeyOnly(bulleted, 'bulleted'),
+ useKeyOnly(link, 'link'),
+ useKeyOnly(ordered, 'ordered'),
+ useKeyOnly(animated, 'animated'),
+ useKeyOnly(celled, 'celled'),
+ useKeyOnly(divided, 'divided'),
+ useKeyOnly(horizontal, 'horizontal'),
+ useKeyOnly(inverted, 'inverted'),
+ useKeyOrValueAndKey(relaxed, 'relaxed'),
+ useKeyOnly(selection, 'selection'),
+ 'list',
+ className
+ )
+
+ const rest = getUnhandledProps(List, props)
+
+ return (
+
+ {children}
+
+ )
+}
+
+List.Item = ListItem
+List.ItemIcon = Icon
+List.ItemImage = Image
+List.ItemHeader = ItemHeader
+List.ItemContent = Content
+List.ItemDescription = Description
+
+List._meta = {
+ library: META.library.semanticUI,
+ name: 'List',
+ type: META.type.element,
+ props: {
+ size: sui.sizes,
+ aligned: sui.verticalAlignments,
+ relaxed: 'very',
+ },
+}
+
+List.propTypes = {
+ /** Primary content of the List */
+ children: PropTypes.node,
+
+ /** Classes to add to the list className. */
+ className: PropTypes.string,
+
+ /** List can be a variety of sizes */
+ size: PropTypes.oneOf(List._meta.props.size),
+
+ /** List can be aligned vertically top, middle, bottom */
+ aligned: PropTypes.oneOf(List._meta.props.aligned),
+
+ /** List can be bulleted */
+ bulleted: PropTypes.bool,
+
+ /** List can be formatted for navigation links */
+ link: PropTypes.bool,
+
+ /** List can be ordered numerically */
+ ordered: PropTypes.bool,
+
+ /** List can animate to set the current item apart from the list */
+ animated: PropTypes.bool,
+
+ /** List can divide its items into cells */
+ celled: PropTypes.bool,
+
+ /** List can show divisions between content */
+ divided: PropTypes.bool,
+
+ /** List can be formatted to have items appear horizontally */
+ horizontal: PropTypes.bool,
+
+ /** List can be inverted to appear on a dark background */
+ inverted: PropTypes.bool,
+
+ /** List can relax its padding to provide more negative space */
+ relaxed: PropTypes.oneOf(
+ List._meta.props.relaxed,
+ PropTypes.bool
+ ),
+
+ /** A selection list formats list items as possible choices */
+ selection: PropTypes.bool,
}
+
+export default List
diff --git a/src/utils/semanticUtils.js b/src/utils/semanticUtils.js
index b7b9544efd..02d395c018 100644
--- a/src/utils/semanticUtils.js
+++ b/src/utils/semanticUtils.js
@@ -15,4 +15,5 @@ export const colors = [
]
export const sizes = ['mini', 'tiny', 'small', 'medium', 'large', 'big', 'huge', 'massive']
export const textAlignments = ['left', 'center', 'right', 'justified']
+export const verticalAlignments = ['top', 'middle', 'bottom']
export const floats = ['left', 'right']
diff --git a/test/specs/elements/List/List-test.js b/test/specs/elements/List/List-test.js
new file mode 100644
index 0000000000..074a36a4f3
--- /dev/null
+++ b/test/specs/elements/List/List-test.js
@@ -0,0 +1,34 @@
+import React from 'react'
+
+import List from 'src/elements/List/List'
+import * as common from 'test/specs/commonTests'
+
+describe('List', () => {
+ common.isConformant(List)
+ common.rendersChildren(List)
+ common.hasUIClassName(List)
+
+ common.propValueOnlyToClassName(List, 'size')
+ common.propKeyAndValueToClassName(List, 'aligned')
+
+ common.propKeyOnlyToClassName(List, 'bulleted')
+ common.propKeyOnlyToClassName(List, 'link')
+ common.propKeyOnlyToClassName(List, 'ordered')
+ common.propKeyOnlyToClassName(List, 'animated')
+ common.propKeyOnlyToClassName(List, 'celled')
+ common.propKeyOnlyToClassName(List, 'divided')
+ common.propKeyOnlyToClassName(List, 'horizontal')
+ common.propKeyOnlyToClassName(List, 'inverted')
+ common.propKeyOnlyToClassName(List, 'selection')
+
+ /**
+ * The correct test for 'relaxed' would be something that
+ * tests for useKeyOrValueAndKey which doesn't seem to be
+ * available.
+ */
+
+ it('renders a element', () => {
+ shallow(
)
+ .should.have.tagName('div')
+ })
+})