├── .gitignore
├── LICENSE
├── README.md
├── now.json
├── package.json
├── public
├── favicon.png
├── index.html
└── meta.png
├── src
├── App
│ ├── index.js
│ └── style.js
├── Tile
│ ├── index.js
│ └── style.js
├── Tiles
│ ├── index.js
│ └── style.js
├── global-styles.js
└── index.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Maximilian
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Color Schemer](https://colors.styled-components.com)
2 |
3 | **[colors.styled-components.com](https://colors.styled-components.com)**
4 |
5 | [](https://colors.styled-components.com)
6 |
7 | A demo React app built with [`💅 styled-components`](https://github.com/styled-components/styled-components) and [`✨ polished`](https://github.com/styled-components/polished).
8 |
9 | ## Structure
10 |
11 | Every component has a folder beneath the `src/` folder, with an `index.js` containing the component and a `style.js` containing the styled components used within that component.
12 |
13 | ```sh
14 | colors
15 | ├── App
16 | ├── Tile
17 | ├── Tiles
18 | ├── global-styles.js # The global styles
19 | └── index.js
20 | ```
21 |
22 | ```
23 | ┌───────────────────────────────────────────────────────────────────┐
24 | │ │
25 | │┌─────────────────────────────────────────────────────────────────┐│
26 | ││ ││
27 | ││ ││
28 | ││ ││
29 | ││ ││
30 | ││ ││
31 | │└─────────────────────────────────────────────────────────────────┘│
32 | │┌─────────────────────────────────────────────────────────────────┐│
33 | ││ ││
34 | ││┌───────────┐┌───────────┐┌───────────┐┌───────────┐┌───────────┐││
35 | │││ ││ ││ ││ ││ │││
36 | │││ ││ ││ ││ ││ │││
37 | │││ ││ ││ ││ ││ │││
38 | ││└───────────┘└───────────┘└───────────┘└───────────┘└───────────┘││
39 | │└─────────────────────────────────────────────────────────────────┘│
40 | └───────────────────────────────────────────────────────────────────┘
41 | ```
42 |
43 | ## Calculation
44 |
45 | We take the entered color, convert it to HSL and render the same hue and saturation with lightness' of `0.1`, `0.3`, `0.5`, `0.7` and `0.9`.
46 |
47 | ## Running locally
48 |
49 | ```sh
50 | git clone https://github.com/styled-components/color-schemer
51 | cd color-schemer # Go to downloaded directory
52 | npm install # Install dependencies
53 | npm start # Start the development server
54 | ```
55 |
56 | ## Uses
57 |
58 | - [`create-react-app`](https://github.com/facebookincubator/create-react-app)
59 | - [💅 `styled-components`](https://github.com/styled-components/styled-components)
60 | - [✨ `polished`](https://github.com/styled-components/polished)
61 | - [clipboard.js](https://clipboardjs.com/)
62 | - [`color-name`](https://npm.im/color-name)
63 |
64 | ## License
65 |
66 | Copyright (c) 2017 Maximilian Stoiber. Licensed under the MIT License, see the [LICENSE](LICENSE) file for more information.
67 |
--------------------------------------------------------------------------------
/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "name": "color-schemer",
4 | "builds": [
5 | { "src": "package.json", "use": "@now/static-build" }
6 | ],
7 | "routes": [
8 | {"src": "^/static/(.*)", "dest": "/static/$1"},
9 | {"src": "^/favicon.ico", "dest": "/favicon.ico"},
10 | {"src": "^/asset-manifest.json", "dest": "/asset-manifest.json"},
11 | {"src": "^/manifest.json", "dest": "/manifest.json"},
12 | {"src": "^/(.*)", "dest": "/index.html"}
13 | ]
14 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "colors",
3 | "version": "0.1.0",
4 | "private": true,
5 | "devDependencies": {
6 | "gh-pages": "^0.12.0",
7 | "lint-staged": "^3.3.1",
8 | "pre-commit": "^1.2.2",
9 | "prettier": "^0.20.0",
10 | "react-scripts": "2.1.1"
11 | },
12 | "dependencies": {
13 | "clipboard": "^1.6.1",
14 | "color-name": "^1.1.4",
15 | "polished": "^2.3.1",
16 | "react": "^16.6.3",
17 | "react-dom": "^16.6.3",
18 | "styled-components": "^4.1.2"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test --env=jsdom",
24 | "eject": "react-scripts eject",
25 | "now-build": "react-scripts build && mv build dist",
26 | "lint:staged": "lint-staged"
27 | },
28 | "lint-staged": {
29 | "*.js": [
30 | "prettier --write --single-quote --trailing-comma es5",
31 | "git add"
32 | ]
33 | },
34 | "pre-commit": "lint:staged",
35 | "browserslist": [
36 | ">0.2%",
37 | "not dead",
38 | "not ie <= 11",
39 | "not op_mini all"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/styled-components/color-schemer/cbdbf006ea54b1402836dd5bb9cd77bf28d427ee/public/favicon.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Color Schemer | Built with 💅 styled-components and ✨ polished
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/public/meta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/styled-components/color-schemer/cbdbf006ea54b1402836dd5bb9cd77bf28d427ee/public/meta.png
--------------------------------------------------------------------------------
/src/App/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { invert } from 'polished';
3 | import cssColors from 'color-name';
4 | import GlobalStyles from '../global-styles';
5 | import Tiles from '../Tiles';
6 |
7 | import { BigTile, Input, Title, ForkBanner, Link, Wrapper } from './style';
8 |
9 | const IS_HEX_WITHOUT_HASH = /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i;
10 |
11 | let inverted, color;
12 | class App extends Component {
13 | state = {
14 | color: '#65daa2',
15 | };
16 |
17 | changeColor = evt => {
18 | this.setState({
19 | color: evt.target.value,
20 | });
21 | };
22 |
23 | render() {
24 | try {
25 | // Handle color names (e.g. "red")
26 | let temp = cssColors[this.state.color];
27 | if (temp) {
28 | temp = `rgb(${temp[0]}, ${temp[1]}, ${temp[2]})`;
29 | } else {
30 | temp = this.state.color;
31 | if (IS_HEX_WITHOUT_HASH.test(temp)) {
32 | temp = `#${temp}`;
33 | }
34 | }
35 | // This will throw if this.state.color is invalid,
36 | // leaving us with the old colors if somebody enters
37 | // an invalid color
38 | inverted = invert(temp);
39 | color = temp;
40 | } catch (err) {}
41 | return (
42 |
43 |
44 |
45 | Color Schemer
46 |
53 |
54 |
55 |
61 |
62 |
63 |
64 | );
65 | }
66 | }
67 |
68 | export default App;
69 |
--------------------------------------------------------------------------------
/src/App/style.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const BigTile = styled.div`
4 | background: ${props => props.bg || '#6cc0e5'};
5 | width: 100%;
6 | height: 50vh;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | `;
11 |
12 | export const Input = styled.input`
13 | background: transparent;
14 | border: none;
15 | color: ${props => props.color};
16 | font-size: 24px;
17 | font-family: monaco,Consolas,Lucida Console,monospace;
18 | width: ${props => `${props.value.length * 16 || 96}px`};
19 | text-align: center;
20 | border-bottom: 1px solid ${props => props.color};
21 |
22 | &:focus,
23 | &:hover {
24 | outline: none;
25 | }
26 | `;
27 |
28 | export const Title = styled.h1`
29 | position: absolute;
30 | top: 0;
31 | color: ${props => props.color};
32 | `;
33 |
34 | export const ForkBanner = styled.img`
35 | position: absolute;
36 | top: 0;
37 | right: 0;
38 | border: 'none';
39 | `;
40 |
41 | export const Link = styled.a``;
42 |
43 | export const Wrapper = styled.div``;
44 |
--------------------------------------------------------------------------------
/src/Tile/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { findDOMNode } from 'react-dom';
3 | import { invert } from 'polished';
4 | import Clipboard from 'clipboard';
5 | import { Wrapper, Text } from './style';
6 |
7 | class Tile extends React.Component {
8 | state = {
9 | text: this.props.color,
10 | };
11 |
12 | // Set the text of the tile temporarily, reverting
13 | // back to the color after one second
14 | setText = text => {
15 | this.setState({
16 | text: text,
17 | });
18 | setTimeout(
19 | () => {
20 | this.setState({
21 | text: this.props.color,
22 | });
23 | },
24 | 1000
25 | );
26 | };
27 |
28 | componentDidMount() {
29 | const clipboard = new Clipboard(findDOMNode(this.tile));
30 | clipboard.on('success', () => {
31 | this.setText('Copied! 💯');
32 | });
33 | clipboard.on('error', function(e) {
34 | this.setText('Copying failed 😢');
35 | });
36 | }
37 |
38 | render() {
39 | const { color } = this.props;
40 | return (
41 | this.tile = comp}
44 | data-clipboard-text={color}
45 | >
46 | {this.state.text}
47 |
48 | );
49 | }
50 | }
51 |
52 | export default Tile;
53 |
--------------------------------------------------------------------------------
/src/Tile/style.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Wrapper = styled.button`
4 | background: ${props => props.bg};
5 | height: 50vh;
6 | width: 20%;
7 | display: flex;
8 | align-items: center;
9 | justify-content: center;
10 | border: none;
11 | display: block;
12 | outline: none;
13 | cursor: pointer;
14 |
15 | @media screen and (max-aspect-ratio: 2/3) {
16 | width: 100%;
17 | height: 10vh;
18 | }
19 | `;
20 |
21 | export const Text = styled.p`
22 | font-size: 1.75em;
23 | color: ${props => props.color};
24 | `;
25 |
--------------------------------------------------------------------------------
/src/Tiles/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { setLightness } from 'polished';
3 |
4 | import Tile from '../Tile';
5 | import { Wrapper } from './style';
6 |
7 | export default ({ color }) => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/src/Tiles/style.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Wrapper = styled.div`
4 | display: flex;
5 | flex-direction: row;
6 |
7 | @media screen and (max-aspect-ratio: 2/3) {
8 | flex-direction: column;
9 | }
10 | `;
11 |
--------------------------------------------------------------------------------
/src/global-styles.js:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 |
3 | export default createGlobalStyle`
4 | html,
5 | #root,
6 | body {
7 | width: 100%;
8 | height: 100%;
9 | margin: 0;
10 | padding: 0;
11 | font-size: 16px;
12 | font-family: Andale Mono,AndaleMono,monospace;
13 | }
14 |
15 | @media screen and (min-aspect-ratio: 2/3) {
16 | overflow: hidden;
17 | }
18 | `;
19 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------