Skip to content

Commit

Permalink
First part practice day 1 => render and compose
Browse files Browse the repository at this point in the history
  • Loading branch information
Augustin Le Fèvre committed Feb 6, 2017
1 parent a39cd19 commit 26b498a
Show file tree
Hide file tree
Showing 16 changed files with 198 additions and 2 deletions.
1 change: 1 addition & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Expand Down
2 changes: 1 addition & 1 deletion src/index.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
body {
margin: 0;
padding: 0;
font-family: sans-serif;
font-family: 'Open Sans', sans-serif;
}

#root {
Expand Down
4 changes: 3 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ import 'purecss/build/pure.css';
// Components
// import './examples/propTypesDefaultProps';
// import './examples/lifeCycle';
import './examples/children';
// import './examples/children';

import './practice/day1/app';
Empty file added src/practice/day1/app.css
Empty file.
19 changes: 19 additions & 0 deletions src/practice/day1/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom';

import ContactList from './contactList';
import contacts from './mockData';

const App = () => {
return (
<div>
<h1>My contacts</h1>
<ContactList list={contacts} />
</div>
);
};

ReactDOM.render(
<App />,
document.getElementById('root'),
)
13 changes: 13 additions & 0 deletions src/practice/day1/contact.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.contact {
width: 400px;

display: flex;
flex-direction: column;
padding: 16px;
}

.contact__header {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
44 changes: 44 additions & 0 deletions src/practice/day1/contact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, {PropTypes} from 'react';

import './contact.css';

import TwitterHandle from './twitterHandle';
import Keyword from './keyword';
import InlineList from './inlineList';

const contactPropTypes = {
contact: PropTypes.shape({
firstname: PropTypes.string.isRequired,
middleName: PropTypes.string,
lastname: PropTypes.string.isRequired,
twitterHandle: PropTypes.string.isRequired,
keywords: PropTypes.array.isRequired,
}).isRequired,
};

const Contact = ({contact}) => {
const {
firstname,
middleName,
lastname,
twitterHandle,
keywords,
} = contact;

const paddedMiddleName = middleName ? ` ${middleName}.` : '';
const contactName = `${firstname}${paddedMiddleName} ${lastname.toUpperCase()}`;
return (
<div className="contact">
<div className="contact__header">
<div className="contact__name">{contactName}</div>
<TwitterHandle handle={twitterHandle} />
</div>
<InlineList elements={keywords}>
{(element, index) => <Keyword keyword={element} key={index} />}
</InlineList>
</div>
);
};
Contact.propTypes = contactPropTypes;

export default Contact;
7 changes: 7 additions & 0 deletions src/practice/day1/contactList.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.list {
box-shadow: rgba(0, 0, 0, 0.117647) 0px 1px 6px, rgba(0, 0, 0, 0.239216) 0px 1px 4px;
}

.list > div:not(:last-child) {
border-bottom: 1px solid #F1F1F1;
}
18 changes: 18 additions & 0 deletions src/practice/day1/contactList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React, {PropTypes} from 'react';

import './contactList.css';

import Contact from './contact';

const contactListPropTypes = {
list: PropTypes.array.isRequired,
};

const ContactList = ({list}) => (
<div className="list">
{list.map(contact => <Contact key={contact.id} contact={contact} />)}
</div>
);
ContactList.propTypes = contactListPropTypes;

export default ContactList;
3 changes: 3 additions & 0 deletions src/practice/day1/inlineList.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.inline-list > span:not(:last-child) {
margin-right: 2px;
}
17 changes: 17 additions & 0 deletions src/practice/day1/inlineList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, {PropTypes} from 'react';

import './inlineList.css';

const inlineListPropTypes = {
children: PropTypes.func.isRequired,
elements: PropTypes.array.isRequired,
};

const InlineList = ({elements, children}) => (
<div className="inline-list">
{elements.map(children)}
</div>
);
InlineList.propTypes = inlineListPropTypes;

export default InlineList;
6 changes: 6 additions & 0 deletions src/practice/day1/keyword.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.keyword {
background-color: #64B5F6;
border-radius: 10px;
color: white;
padding: 1px 5px;
}
14 changes: 14 additions & 0 deletions src/practice/day1/keyword.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React, {PropTypes} from 'react';

import './keyword.css';

const keywordPropTypes = {
keyword: PropTypes.string.isRequired,
};

const Keyword = ({keyword}) => (
<span className="keyword">{keyword}</span>
);
Keyword.propTypes = keywordPropTypes;

export default Keyword;
32 changes: 32 additions & 0 deletions src/practice/day1/mockData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export default [
{
id: 1,
firstname: 'Dan',
lastname: 'Abramov',
twitterHandle: 'dan_abramov',
keywords: ['react', 'fp']
},
{
id: 2,
firstname: 'Kent',
middleName: 'C',
lastname: 'Dodds',
twitterHandle: 'kentcdodds',
keywords: ['react', 'fp'],
},
{
id: 3,
firstname: 'André',
lastname: 'Staltz',
twitterHandle: 'andrestaltz',
keywords: ['cyclejs', 'typescript', 'fp'],

},
{
id: 4,
firstname: 'Todd',
lastname: 'Motto',
twitterHandle: 'toddmotto',
keywords: ['angular', 'typescript']
},
];
10 changes: 10 additions & 0 deletions src/practice/day1/todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Let's create a simple contact list

## Rendering to the DOM
Render
State for rendering empty list
fake async for data ?


To keep in mind? Does this component is supposed to handle that? Is it its responsibility?
A component should do only one thing
10 changes: 10 additions & 0 deletions src/practice/day1/twitterHandle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, {PropTypes} from 'react';

const TwitterHandle = ({handle}) => (
<a href={`https://twitter.com/${handle}`}>{`@${handle}`}</a>
);
TwitterHandle.propTypes = {
handle: PropTypes.string.isRequired,
}

export default TwitterHandle;

0 comments on commit 26b498a

Please sign in to comment.