diff --git a/packages/ffe-lists-react/src/DetailListCard.js b/packages/ffe-lists-react/src/DetailListCard.js
new file mode 100644
index 0000000000..ee606e18cc
--- /dev/null
+++ b/packages/ffe-lists-react/src/DetailListCard.js
@@ -0,0 +1,23 @@
+import React from 'react';
+import classNames from 'classnames';
+import { node, string } from 'prop-types';
+
+const DetailListCard = props => {
+ const { className, children, ...rest } = props;
+
+ return (
+
+ {children}
+
+ );
+};
+
+DetailListCard.defaultProps = {};
+
+DetailListCard.propTypes = {
+ /** Additional classnames */
+ className: string,
+ children: node,
+};
+
+export default DetailListCard;
diff --git a/packages/ffe-lists-react/src/DetailListCard.spec.js b/packages/ffe-lists-react/src/DetailListCard.spec.js
new file mode 100644
index 0000000000..e5e871ae07
--- /dev/null
+++ b/packages/ffe-lists-react/src/DetailListCard.spec.js
@@ -0,0 +1,83 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import DetailListCard from './DetailListCard';
+import DetailListCardItem from './DetailListCardItem';
+
+const getWrapper = props =>
+ shallow(
+
+
+ ,
+ );
+
+const getDetailListCardItemWrapper = props =>
+ shallow(
+ ,
+ );
+
+describe('', () => {
+ it('renders without exploding', () => {
+ const wrapper = getWrapper();
+ expect(wrapper.exists()).toBe(true);
+ expect(wrapper.is('dl')).toBe(true);
+ });
+ it('add classNames correctly', () => {
+ const wrapper = getWrapper({ className: 'test-class' });
+ expect(wrapper.hasClass('ffe-detail-list-card')).toBe(true);
+ expect(wrapper.hasClass('test-class')).toBe(true);
+ });
+});
+
+describe('', () => {
+ it('renders without exploding', () => {
+ const wrapper = getDetailListCardItemWrapper();
+ expect(wrapper.is('div')).toBe(true);
+ expect(wrapper.hasClass('ffe-detail-list-card__item')).toBe(true);
+ });
+ it('adds additional classNames correctly', () => {
+ const wrapper = getDetailListCardItemWrapper({
+ className: 'test-class',
+ });
+ expect(wrapper.hasClass('test-class')).toBe(true);
+ });
+
+ it('render correct element based on element prop', () => {
+ const wrapper = getDetailListCardItemWrapper({ element: 'a' });
+ expect(wrapper.is('a')).toBe(true);
+ });
+ it('adds additional props correctly', () => {
+ const wrapper = getDetailListCardItemWrapper({ href: '#' });
+ expect(wrapper.prop('href')).toBe('#');
+ });
+ it('renders correct label content', () => {
+ const wrapper = getDetailListCardItemWrapper();
+ expect(wrapper.find('dt').exists()).toBe(true);
+ expect(
+ wrapper.find('dt').hasClass('ffe-detail-list-card__item-label'),
+ ).toBe(true);
+ const wrapper2 = getDetailListCardItemWrapper({
+ label: Test Label,
+ });
+ expect(wrapper2.find('dt').contains(Test Label)).toBe(
+ true,
+ );
+ });
+
+ it('renders correct value content', () => {
+ const wrapper = getDetailListCardItemWrapper();
+ expect(wrapper.find('dd').exists()).toBe(true);
+ expect(
+ wrapper.find('dd').hasClass('ffe-detail-list-card__item-value'),
+ ).toBe(true);
+ const wrapper2 = getDetailListCardItemWrapper({
+ value: Test Value,
+ });
+ expect(wrapper2.find('dd').contains(Test Value)).toBe(
+ true,
+ );
+ });
+});
diff --git a/packages/ffe-lists-react/src/DetailListCardItem.js b/packages/ffe-lists-react/src/DetailListCardItem.js
new file mode 100644
index 0000000000..a995facea9
--- /dev/null
+++ b/packages/ffe-lists-react/src/DetailListCardItem.js
@@ -0,0 +1,50 @@
+import React from 'react';
+import classNames from 'classnames';
+import { string, oneOfType, node, func, elementType } from 'prop-types';
+
+const DetailListCardItem = props => {
+ const { className, label, value, element: Element, ...rest } = props;
+
+ const isClickable = rest.onClick || rest.href;
+
+ return (
+
+
+ {typeof label === 'string'
+ ? label
+ : React.cloneElement(label, { ...label.props })}
+
+
+ {typeof value === 'string'
+ ? value
+ : React.cloneElement(value, { ...value.props })}
+
+
+ );
+};
+
+DetailListCardItem.defaultProps = {
+ element: 'div',
+};
+
+DetailListCardItem.propTypes = {
+ /** Additional classnames */
+ className: string,
+ /** The element to render the item as */
+ element: oneOfType([func, string, elementType]),
+ /** Content of the label / left column */
+ label: oneOfType([node, string]).isRequired,
+ /** Content of the value / right column */
+ value: oneOfType([node, string]).isRequired,
+};
+
+export default DetailListCardItem;
diff --git a/packages/ffe-lists-react/src/index.d.ts b/packages/ffe-lists-react/src/index.d.ts
index 1ee593bddb..775479bc09 100644
--- a/packages/ffe-lists-react/src/index.d.ts
+++ b/packages/ffe-lists-react/src/index.d.ts
@@ -32,6 +32,19 @@ export interface DescriptionListProps extends BaseListProps {
horizontal?: boolean;
}
+export interface DetailListCardItemProps {
+ className?: string;
+ element?: HTMLElement | string | React.ElementType;
+ label: React.ReactNode;
+ value: React.ReactNode;
+}
+export interface DetailListCard {
+ className?: string;
+ children:
+ | React.ReactNode
+ | ((props: DetailListCardItemProps) => React.ReactNode);
+}
+
declare class BulletList extends React.Component<
BulletListProps & React.ComponentProps<'ul'>,
any
diff --git a/packages/ffe-lists-react/src/index.js b/packages/ffe-lists-react/src/index.js
index 9b8a2f1241..d9675c4875 100644
--- a/packages/ffe-lists-react/src/index.js
+++ b/packages/ffe-lists-react/src/index.js
@@ -10,6 +10,8 @@ import DescriptionList from './DescriptionList';
import DescriptionListMultiCol from './DescriptionListMultiCol';
import DescriptionListTerm from './DescriptionListTerm';
import DescriptionListDescription from './DescriptionListDescription';
+import DetailListCard from './DetailListCard';
+import DetailListCardItem from './DetailListCardItem';
export {
BulletList,
@@ -24,6 +26,8 @@ export {
DescriptionListMultiCol,
DescriptionListTerm,
DescriptionListDescription,
+ DetailListCard,
+ DetailListCardItem,
};
export default BulletList;