Skip to content

Commit f96a85e

Browse files
committed
feat(Item): added item component wip
1 parent a7e0060 commit f96a85e

File tree

7 files changed

+320
-0
lines changed

7 files changed

+320
-0
lines changed

src/components/Item/Item-test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
import Link from '../Link';
3+
import { shallow } from 'enzyme';
4+
5+
describe('Link', () => {
6+
describe('Renders as expected', () => {
7+
const link = shallow(
8+
<Link href="www.google.com" className="some-class">
9+
A simple link
10+
</Link>
11+
);
12+
it('should use the appropriate link class', () => {
13+
expect(link.hasClass('wfp--link')).toEqual(true);
14+
});
15+
it('should inherit the href property', () => {
16+
expect(link.props().href).toEqual('www.google.com');
17+
});
18+
it('should include child content', () => {
19+
expect(link.text()).toEqual('A simple link');
20+
});
21+
it('should all for custom classes to be applied', () => {
22+
expect(link.hasClass('some-class')).toEqual(true);
23+
});
24+
});
25+
});

src/components/Item/Item.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import classnames from 'classnames';
4+
import settings from '../../globals/js/settings';
5+
const { prefix } = settings;
6+
7+
/** The item component can be used whenever a section should indicate that there is no content available. This can be the case for a item list table or search results. */
8+
export const Item = ({
9+
button,
10+
children,
11+
className,
12+
href,
13+
subText,
14+
icon,
15+
title,
16+
kind = 'large',
17+
...other
18+
}) => {
19+
const classNames = classnames(
20+
{
21+
[`${prefix}--item`]: true,
22+
[`${prefix}--item--${kind}`]: kind,
23+
},
24+
className
25+
);
26+
return (
27+
<div className={classNames} {...other}>
28+
<div className={`${prefix}--item__icon`}>{icon}</div>
29+
<div className={`${prefix}--item__content`}>
30+
{title && <h2 className={`${prefix}--item__title`}>{title}</h2>}
31+
{children && <div className={`${prefix}--item__text`}>{children}</div>}
32+
{subText && <div className={`${prefix}--item__subtext`}>{subText}</div>}
33+
</div>
34+
<div className={`${prefix}--item__button`}>{button}</div>
35+
</div>
36+
);
37+
};
38+
39+
Item.propTypes = {
40+
/**
41+
* Provide the description for the item content
42+
*/
43+
children: PropTypes.node,
44+
45+
/**
46+
* Provide the title for the item contet
47+
*/
48+
title: PropTypes.node,
49+
50+
/**
51+
* Provide the icon for the item content
52+
*/
53+
icon: PropTypes.node,
54+
55+
/**
56+
* Provide one or multiple buttons
57+
*/
58+
button: PropTypes.node,
59+
60+
/**
61+
* Provide a custom className to be applied to the containing <a> node
62+
*/
63+
className: PropTypes.string,
64+
65+
/**
66+
* Provide a kind to use different appearances.
67+
*/
68+
kind: PropTypes.oneOf(['undefined', 'large']),
69+
};
70+
71+
export default Item;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import markdown from './README.mdx';
3+
import Item from '.';
4+
import Button from '../Button';
5+
6+
export default {
7+
title: 'Components/UI Elements/Item',
8+
component: Item,
9+
parameters: {
10+
componentSubtitle: 'Component',
11+
status: 'released',
12+
mdx: markdown,
13+
},
14+
};
15+
16+
export const Regular = (args) => <Item {...args} />;
17+
18+
Regular.args = {
19+
title: 'No entries found',
20+
children: `You haven't yet created an entry`,
21+
kind: 'large',
22+
icon: (
23+
<img
24+
alt="Moving van"
25+
src="https://www.wfp.org/sites/default/files/images/27DA6743-41A0-4970-A9BA-B4B1415CDD2E_0.jpeg"
26+
/>
27+
),
28+
button: <Button kind="accent">New entry</Button>,
29+
};
30+
31+
export const Horizontal = (args) => <Item {...args} />;
32+
33+
Horizontal.args = {
34+
title: 'No entries found',
35+
children: `You haven't yet created an entry`,
36+
subText: `You haven't yet created an entry`,
37+
kind: 'horizontal',
38+
icon: (
39+
<img
40+
alt="Moving van"
41+
src="https://www.wfp.org/sites/default/files/images/27DA6743-41A0-4970-A9BA-B4B1415CDD2E_0.jpeg"
42+
/>
43+
),
44+
button: <Button kind="accent">New entry</Button>,
45+
};

src/components/Item/README.mdx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Empty states are a way to improve the user experience of your product, from onboarding to encouraging users to interact with your app. They are screens in your UI that are not yet full of information. That is to say, they will eventually have content on them when the user populates them.
2+
3+
The component should usually cover the whole area of the section and have a slightly darker background than the regular content. It can be also used for large notification messages.
4+
5+
### Types of empty states
6+
7+
- **First use** – Occurs with a new product or service when there is still nothing to show, such as a new Evernote or Dropbox account.
8+
- **User cleared** – Occurs when users complete actions such as clearing their inbox or task list, and the result is an empty screen.
9+
- **Errors** – These occur when something goes wrong, or when there are issues such as a mobile phone going offline due to network problems.
10+
- **No results/No data** – Occurs when there is nothing to show. This can happen if someone performs a search and the query is empty or there isn’t data available to show (when filtering for a date-range that has no data for example).
11+
12+
### When to use
13+
14+
- ✓ Can be the case for a empty list table or search results
15+
- ✓ Cover the whole area where normally content would be displayed
16+
- ✓ Add personality by adding an illustration or icon (for example by using FontAwesome)
17+
- ✓ Tell your user to do something: provide a call-to-action button
18+
- ✓ Can be also used for large notification messages
19+
20+
### Related
21+
22+
[Button](?path=/docs/components-button--button-regular)
23+
24+
### Reference
25+
26+
[Breakfree Graphics Empty States – The Most Overlooked Aspect of UX](https://www.breakfreegraphics.com/design-blog/empty-states-the-most-overlooked-aspect-of-ux/)
27+
28+
[justinmind Everything you need to know about empty state design](https://www.justinmind.com/blog/everything-you-need-to-know-about-empty-state-design/)

src/components/Item/_item.scss

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
//-----------------------------
2+
// Link
3+
//-----------------------------
4+
5+
@import '../../globals/scss/colors';
6+
@import '../../globals/scss/vars';
7+
@import '../../globals/scss/layout';
8+
@import '../../globals/scss/typography';
9+
@import '../../globals/scss/helper-mixins';
10+
@import '../../globals/scss/import-once';
11+
@import '../../globals/scss/css--reset';
12+
13+
@include exports('item') {
14+
.#{$prefix}--item {
15+
padding: $spacing-lg;
16+
margin: 0;
17+
display: flex !important;
18+
background: var(--ui-02);
19+
text-align: center;
20+
flex-direction: column;
21+
align-items: center;
22+
justify-content: center;
23+
24+
&--section {
25+
padding: $spacing-xl 0;
26+
text-align: left;
27+
flex-direction: row;
28+
justify-content: space-between;
29+
h2 {
30+
@include typescale('epsilon');
31+
}
32+
p {
33+
opacity: 0.6;
34+
@include typescale('caption');
35+
}
36+
.#{$prefix}--empty__icon {
37+
margin-bottom: 1em;
38+
display: none;
39+
svg,
40+
.svg-inline--fa {
41+
width: 5rem;
42+
height: 5rem;
43+
path {
44+
fill: $interactive-01;
45+
}
46+
margin-bottom: $spacing-xs;
47+
}
48+
}
49+
}
50+
&--large {
51+
min-height: 17rem;
52+
padding: 2rem 0;
53+
height: 100%;
54+
width: 100%;
55+
56+
> div {
57+
margin-top: 0rem;
58+
}
59+
60+
h2 {
61+
margin-bottom: $spacing-xs;
62+
}
63+
64+
p {
65+
color: var(--ui-05);
66+
}
67+
.#{$prefix}--item__button {
68+
margin-top: $spacing-md;
69+
.wfp--btn {
70+
margin: $spacing-2xs;
71+
}
72+
}
73+
}
74+
75+
&--horizontal {
76+
padding: 1em;
77+
height: 100%;
78+
width: 100%;
79+
flex-direction: row;
80+
81+
text-align: left;
82+
83+
> div {
84+
margin-top: 0rem;
85+
}
86+
87+
h2 {
88+
margin-bottom: $spacing-2xs;
89+
font-size: 1em;
90+
}
91+
92+
p {
93+
color: var(--ui-05);
94+
}
95+
.#{$prefix}--item__button {
96+
.wfp--btn {
97+
margin: $spacing-2xs;
98+
}
99+
}
100+
}
101+
.#{$prefix}--item__content {
102+
flex: 1;
103+
}
104+
.#{$prefix}--item__text {
105+
flex: 1;
106+
font-size: 0.9em;
107+
}
108+
.#{$prefix}--item__subtext {
109+
color: var(--text-02);
110+
margin-top: $spacing-2xs;
111+
font-size: 0.9em;
112+
}
113+
.#{$prefix}--item__icon {
114+
width: 5rem;
115+
margin-right: 1em;
116+
img {
117+
width: 100%;
118+
}
119+
}
120+
}
121+
122+
.#{$prefix}--item__icon {
123+
svg,
124+
.svg-inline--fa {
125+
width: 5rem;
126+
height: 5rem;
127+
path {
128+
fill: $interactive-01;
129+
}
130+
margin-bottom: $spacing-xs;
131+
}
132+
.#{$prefix}--item--large & {
133+
padding: 0 2rem;
134+
//height: 100%;
135+
img {
136+
width: 35rem;
137+
max-width: 100%;
138+
max-height: 15rem;
139+
height: auto;
140+
}
141+
svg,
142+
.svg-inline--fa {
143+
width: 15rem;
144+
height: 15rem;
145+
}
146+
margin-bottom: $spacing-lg;
147+
}
148+
}
149+
}

src/components/Item/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default from './Item';

src/globals/scss/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ $deprecations--message: 'Deprecated code was found, this code will be removed be
8383
@import '../../components/Card/card';
8484
@import '../../components/ContentSwitcher/content-switcher';
8585
@import '../../components/List/list';
86+
@import '../../components/Item/item.scss';
8687
@import '../../components/Loading/loading';
8788
@import '../../components/Modal/modal';
8889
@import '../../components/Module/module';

0 commit comments

Comments
 (0)