Skip to content

Commit deefd64

Browse files
committed
init base
1 parent 059e004 commit deefd64

File tree

23 files changed

+310
-50
lines changed

23 files changed

+310
-50
lines changed

.storybook/addons.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import "@storybook/addon-actions/register";
2+
import "@storybook/addon-links/register";

.storybook/config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { configure } from "@storybook/react";
2+
3+
// import default styles
4+
import "../src/styles";
5+
6+
// automatically import all files ending in *.stories.js
7+
configure(require.context("../src/stories", true, /\.stories\.js$/), module);

package.json

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"scripts": {
66
"build": "react-app-rewired build",
77
"start": "react-app-rewired start",
8-
"test": "react-app-rewired test --watchAll=false"
8+
"test": "react-app-rewired test --watchAll=false",
9+
"storybook": "start-storybook -p 9009 -s public",
10+
"build-storybook": "build-storybook -s public"
911
},
1012
"browserslist": {
1113
"production": [
@@ -23,15 +25,26 @@
2325
"extends": "react-app"
2426
},
2527
"dependencies": {
26-
"@testing-library/jest-dom": "^4.2.4",
27-
"@testing-library/react": "^9.4.0",
28-
"@testing-library/user-event": "^8.0.2",
28+
"@fortawesome/fontawesome-svg-core": "^1.2.26",
29+
"@fortawesome/free-solid-svg-icons": "^5.12.0",
30+
"@fortawesome/react-fontawesome": "^0.1.8",
31+
"bootstrap": "^4.4.1",
2932
"react": "^16.12.0",
33+
"react-bootstrap": "^1.0.0-beta.16",
3034
"react-dom": "^16.12.0",
3135
"react-scripts": "^3.3.0"
3236
},
3337
"devDependencies": {
38+
"@storybook/addon-actions": "^5.2.8",
39+
"@storybook/addon-links": "^5.2.8",
40+
"@storybook/addons": "^5.2.8",
41+
"@storybook/react": "^5.2.8",
42+
"@testing-library/dom": "^6.11.0",
43+
"@testing-library/jest-dom": "^4.2.4",
44+
"@testing-library/react": "^9.4.0",
45+
"@testing-library/react-hooks": "^3.2.1",
3446
"jest-tap-reporter": "^1.9.0",
35-
"react-app-rewired": "^2.1.5"
47+
"react-app-rewired": "^2.1.5",
48+
"react-test-renderer": "^16.12.0"
3649
}
3750
}

src/App.css

Lines changed: 0 additions & 38 deletions
This file was deleted.

src/App.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import React from "react";
2+
import Card from "react-bootstrap/Card";
3+
import { MessageForm } from "./components/MessageForm";
4+
import { USER } from "./config";
25

3-
const App = () => {
4-
return <div>Welcome to CodeRoad</div>;
5-
};
6+
const App = () => (
7+
<div className="App">
8+
<Card className="Home">
9+
<Card.Header className="Home_Title">Home</Card.Header>
10+
<Card.Body className="Home_Body">
11+
<MessageForm user={USER} />
12+
</Card.Body>
13+
</Card>
14+
</div>
15+
);
616

717
export default App;

src/components/Avatar/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
import BootstrapImage from "react-bootstrap/Image";
3+
4+
export const Avatar = ({ image }) => (
5+
<BootstrapImage src={image} roundedCircle style={{ height: 49, width: 49 }} />
6+
);

src/components/Card/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from "react";
2+
3+
import BootstrapCard from "react-bootstrap/Card";
4+
import { Avatar } from "../Avatar";
5+
import "./styles.css";
6+
7+
export const Card = ({ children, profile_image, className, ...rest }) => {
8+
return (
9+
<BootstrapCard className={`Card ${className || ""}`} {...rest}>
10+
<div className="Card_LeftColumn">
11+
<Avatar image={profile_image} />
12+
</div>
13+
<div className="Card_RightColumn">{children}</div>
14+
</BootstrapCard>
15+
);
16+
};

src/components/Card/styles.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.Card {
2+
display: flex;
3+
flex-direction: row;
4+
padding: 1rem;
5+
width: 100%;
6+
}
7+
8+
.Card_LeftColumn {
9+
display: flex;
10+
width: 50px;
11+
justify-content: center;
12+
}
13+
14+
.Card_RightColumn {
15+
padding-left: 1rem;
16+
width: 100%;
17+
}

src/components/Icon/Button.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from "react";
2+
3+
export const IconButton = ({ children, className, ...rest }) => (
4+
<button className={`Icon_Button ${className}`} {...rest}>
5+
{children}
6+
</button>
7+
);

src/components/Icon/CountWrapper.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from "react";
2+
3+
export const IconCountWrapper = ({ children, count, ...rest }) => (
4+
<div className="Icon_Countable" {...rest}>
5+
{children}
6+
{count > 0 && <span className="Icon_Count">{count}</span>}
7+
</div>
8+
);

src/components/Icon/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from "react";
2+
3+
import * as SvgIcon from "@fortawesome/free-solid-svg-icons";
4+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5+
import "./styles.css";
6+
7+
const icons = {
8+
comment: SvgIcon.faComment,
9+
retweet: SvgIcon.faRetweet,
10+
favorite: SvgIcon.faHeart,
11+
share: SvgIcon.faShare,
12+
loading: SvgIcon.faSpinner
13+
};
14+
15+
export const Icon = ({ icon, active, highlight, ...rest }) => (
16+
<FontAwesomeIcon
17+
icon={icons[icon]}
18+
color={active ? highlight : "lightgrey"}
19+
{...rest}
20+
/>
21+
);
22+
23+
export { IconButton } from "./Button";
24+
export { IconCountWrapper } from "./CountWrapper";

src/components/Icon/styles.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
.Icon_Button {
2+
border: none;
3+
background-color: inherit;
4+
padding: 0;
5+
}
6+
7+
.Icon_Button:hover {
8+
/* input styles */
9+
}
10+
11+
.Icon_Button:focus {
12+
outline: none !important;
13+
}
14+
15+
.Icon_Countable {
16+
display: flex;
17+
flex-direction: row;
18+
justify-content: space-between;
19+
align-items: center;
20+
width: 40px;
21+
height: 30px;
22+
color: lightgrey;
23+
}
24+
25+
.Icon_Count {
26+
font-size: 12px;
27+
color: darkgrey;
28+
-webkit-touch-callout: none; /* iOS Safari */
29+
-webkit-user-select: none; /* Safari */
30+
-khtml-user-select: none; /* Konqueror HTML */
31+
-moz-user-select: none; /* Firefox */
32+
-ms-user-select: none; /* Internet Explorer/Edge */
33+
user-select: none; /* Non-prefixed */
34+
}

src/components/MessageForm/index.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from "react";
2+
import Form from "react-bootstrap/Form";
3+
import Button from "react-bootstrap/Button";
4+
5+
import { Card } from "../Card";
6+
import { MAX_MESSAGE_TEXT_LENGTH } from "../../config";
7+
import "./styles.css";
8+
9+
export const MessageForm = ({ user }) => {
10+
let text = "";
11+
12+
const handleChange = event => {
13+
event.preventDefault();
14+
const updatedText = event.target.value;
15+
text = updatedText; // TODO: update text on change
16+
};
17+
18+
return (
19+
<Card className="MessageForm" profile_image={user.profile_image}>
20+
<Form>
21+
<Form.Group>
22+
<Form.Control
23+
className="MessageForm_TextArea"
24+
aria-label="message-form"
25+
as="textarea"
26+
rows="3"
27+
placeholder="What's happening?"
28+
value={text}
29+
onChange={handleChange}
30+
/>
31+
</Form.Group>
32+
<div className="MessageForm_Options">
33+
<span className="MessageForm_TextCount" title="text-count">
34+
0 / {MAX_MESSAGE_TEXT_LENGTH} {/* TODO: update text letter count */}
35+
</span>
36+
<Button
37+
className="MessageForm_TweetButton"
38+
variant="primary"
39+
type="submit"
40+
role="tweet"
41+
/* TODO: disable button if no text */
42+
>
43+
Tweet
44+
</Button>
45+
</div>
46+
</Form>
47+
</Card>
48+
);
49+
};

src/components/MessageForm/styles.css

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.MessageForm {
2+
border-bottom: 4px solid lightgrey;
3+
}
4+
5+
.MessageForm_Form {
6+
font-size: 15px;
7+
}
8+
9+
.MessageForm_TextArea {
10+
border: none;
11+
padding-left: 15px;
12+
padding-right: 15px;
13+
resize: none;
14+
}
15+
16+
.MessageForm_TextArea:focus {
17+
border: none;
18+
box-shadow: none;
19+
}
20+
21+
.MessageForm_Options {
22+
display: flex;
23+
align-items: center;
24+
justify-content: flex-end;
25+
margin: 0px 2px;
26+
}
27+
28+
.MessageForm_TextCount {
29+
margin-right: 15px;
30+
}
31+
32+
.MessageForm_TweetButton {
33+
line-height: 1;
34+
font-weight: bold;
35+
text-align: center;
36+
height: 39px;
37+
min-width: 63px;
38+
border-radius: 9999px;
39+
}

src/config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Current User
2+
// TODO: implement user management
3+
export const USER = {
4+
id_str: "1",
5+
name: "Shawn McKay",
6+
screen_name: "Sh_McK",
7+
profile_image:
8+
"https://pbs.twimg.com/profile_images/674551835319922689/ahFe0UPL_reasonably_small.png"
9+
};
10+
11+
// Variables
12+
export const MAX_MESSAGE_TEXT_LENGTH = 280;

src/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import React from "react";
22
import ReactDOM from "react-dom";
3-
import "./styles/index.css";
3+
4+
// load library styles before app styles
5+
import "./styles";
6+
47
import App from "./App";
58

69
ReactDOM.render(<App />, document.getElementById("root"));

src/stories/0-Welcome.stories.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from "react";
2+
import { linkTo } from "@storybook/addon-links";
3+
import { Welcome } from "@storybook/react/demo";
4+
5+
export default {
6+
title: "Welcome"
7+
};
8+
9+
export const toStorybook = () => <Welcome showApp={linkTo("Button")} />;
10+
11+
toStorybook.story = {
12+
name: "to Storybook"
13+
};

src/stories/1-MessageForm.stories.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from "react";
2+
import { MessageForm } from "../components/MessageForm";
3+
import { USER } from "../config";
4+
5+
export default {
6+
title: "MessageForm"
7+
};
8+
9+
export const messageForm = () => <MessageForm user={USER} />;

src/styles/App.css

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
.App {
2+
position: relative;
3+
display: flex;
4+
justify-content: center;
5+
background-color: rgb(235, 235, 235);
6+
width: 100%;
7+
height: 100%;
8+
padding: 0;
9+
min-height: 100vh;
10+
}
11+
12+
.Home {
13+
padding: 0;
14+
width: 600px;
15+
background-color: white;
16+
border-left: 1px solid lightgrey;
17+
border-right: 1px solid lightgrey;
18+
}
19+
20+
.Home_Title {
21+
font-weight: bold;
22+
}
23+
24+
.Home_Body {
25+
display: flex;
26+
flex-direction: column;
27+
padding: 0;
28+
}
File renamed without changes.

0 commit comments

Comments
 (0)