├── .eslintrc
├── .gitignore
├── README.md
├── package.json
├── public
├── favicon.ico
├── index.html
└── manifest.json
├── src
├── App.css
├── App.js
├── App.test.js
├── ControlsRenderer.jsx
├── IconRenderer.jsx
├── index.css
├── index.js
├── material-colors.json
└── registerServiceWorker.js
└── yarn.lock
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "react-app"
3 | }
4 |
--------------------------------------------------------------------------------
/.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.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # VSCode custom icon generator
2 |
3 | [Simple app](http://bouveronmaxi.me/vscode-icon-generator/) that makes creating
4 | a new VSCode icon color scheme easier. :art:
5 |
6 | Widely inspired by [vscode-icons](https://github.com/dhanishgajjar/vscode-icons)
7 |
8 | Features :
9 |
10 | * [x] Generate random icon color scheme :game_die:
11 | * [x] Simple color picker :art:
12 | * [x] Color picker with material design colors built-in :art:
13 | * [x] Download SVG icon :arrow_down:
14 | * [ ] Download png icon (it _may_ be possible) :arrow_down:
15 | * [x] "Beautiful" user interface :art:
16 | * [x] Deploy app on Github pages :rocket: ->
17 | [HERE](http://bouveronmaxi.me/vscode-icon-generator/)
18 | * [ ] Download native icon formats (pretty sure it's not possible) :arrow_down:
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-icon-generator",
3 | "version": "0.1.0",
4 | "homepage": "http://bouveronmaxi.me/vscode-icon-generator",
5 | "private": true,
6 | "dependencies": {
7 | "gh-pages": "^1.1.0",
8 | "react": "^16.1.1",
9 | "react-color": "^2.13.8",
10 | "react-dom": "^16.1.1",
11 | "react-scripts": "1.0.17"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "predeploy": "npm run build",
18 | "deploy": "gh-pages -d build",
19 | "eject": "react-scripts eject"
20 | },
21 | "devDependencies": {
22 | "babel-eslint": "^8.0.2",
23 | "eslint": "^4.11.0",
24 | "eslint-config-react-app": "^2.0.1",
25 | "eslint-plugin-flowtype": "^2.39.1",
26 | "eslint-plugin-import": "^2.8.0",
27 | "eslint-plugin-jsx-a11y": "^6.0.2",
28 | "eslint-plugin-react": "^7.5.1"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bo-Duke/vscode-icon-generator/16f537f17311ebf36dbfaa9e3d56c8d70dd4fa28/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | VSCode Icon Generator
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "VSCode icon generator",
3 | "name": "CVSCode custom icon generator",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .app-wrapper {
2 | width: 100%;
3 | max-width: 700px;
4 | margin-left: auto;
5 | margin-right: auto;
6 | display: grid;
7 | grid-template-areas:
8 | 'head head'
9 | 'form icon-render';
10 | grid-template-rows: 90px 1fr;
11 | grid-template-columns: 200px 1fr;
12 | }
13 |
14 | .control-form {
15 | grid-area: form;
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: flex-start;
19 | align-items: flex-start;
20 | }
21 |
22 | .control-form > div {
23 | margin-bottom: 5px;
24 | }
25 |
26 | .icon-renderer {
27 | grid-area: icon-render;
28 | display: flex;
29 | justify-content: center;
30 | align-items: flex-start;
31 | }
32 |
33 | .header {
34 | grid-area: head;
35 | display: flex;
36 | justify-content: center;
37 | align-items: center;
38 | font-size: 1.4em;
39 | }
40 |
41 | /* Color picker */
42 |
43 | .color-button {
44 | padding: 5px;
45 | height: 14px;
46 | background: #fff;
47 | border-radius: 1px;
48 | box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
49 | display: inline-block;
50 | cursor: pointer;
51 | }
52 |
53 | .color-button-inside {
54 | width: 36px;
55 | height: 14px;
56 | border-radius: 2px;
57 | }
58 |
59 | .color-picker {
60 | position: absolute;
61 | z-index: 2;
62 | }
63 |
64 | .color-picker-close {
65 | position: fixed;
66 | top: 0px;
67 | right: 0px;
68 | bottom: 0px;
69 | left: 0px;
70 | }
71 |
72 | .color-picker-label {
73 | display: flex;
74 | flex-direction: row;
75 | justify-content: space-between;
76 | align-items: center;
77 | width: 200px;
78 | }
79 |
80 | /* Download button
81 | source (because I'm lazy enough to make a simple button) https://codepen.io/mohaiman/pen/jqKzVb?editors=0100
82 | */
83 | .download-button {
84 | text-align: center;
85 | text-decoration: none;
86 | color: white;
87 | border-radius: 4px;
88 | background-color: #d35400;
89 | border: none;
90 | padding: 20px;
91 | width: 170px;
92 | margin-top: 20px;
93 | transition: all 0.5s;
94 | display: block;
95 | font-size: 0.9em;
96 | }
97 |
98 | .download-button > span {
99 | display: inline-block;
100 | position: relative;
101 | transition: 0.5s;
102 | }
103 |
104 | .download-button > span:after {
105 | content: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4gICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4gICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==);
106 | position: absolute;
107 | opacity: 0;
108 | top: -3px;
109 | right: -20px;
110 | transition: 0.5s;
111 | }
112 |
113 | .download-button:hover span {
114 | padding-right: 30px;
115 | }
116 |
117 | .download-button:hover span:after {
118 | opacity: 1;
119 | right: 0;
120 | }
121 |
122 | .random-button {
123 | margin-top: 15px;
124 | width: 100%;
125 | text-align: center;
126 | }
127 |
128 | .random-button > button {
129 | cursor: pointer;
130 | text-decoration: none;
131 | color: white;
132 | border-radius: 4px;
133 | background-color: #006dd3;
134 | border: none;
135 | padding: 5px;
136 | transition: background-color 0.5s;
137 | }
138 |
139 | .random-button > button:hover {
140 | background-color: #53acff;
141 | }
142 |
143 | .control-form input[type='range'] {
144 | width: 100%;
145 | margin-left: 0;
146 | }
147 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOMServer from 'react-dom/server'
3 | import IconRenderer from './IconRenderer'
4 | import ControlsRenderer from './ControlsRenderer'
5 | import COLORS from './material-colors.json'
6 | import './App.css'
7 |
8 | class App extends React.Component {
9 | constructor(props) {
10 | super(props)
11 | const background = this.randomColor().background
12 | const foreground = this.randomColor().foreground
13 | this.state = {
14 | background,
15 | foreground,
16 | foreground2: foreground,
17 | size: 200,
18 | separateForeground: false,
19 | }
20 | }
21 |
22 | randomColor = () => {
23 | const randomNum = Math.floor(Math.random() * COLORS.length)
24 | return COLORS[randomNum]
25 | }
26 |
27 | onRandom = () => {
28 | const background = this.randomColor().background
29 | const foreground = this.randomColor().foreground
30 | this.setState({
31 | background,
32 | foreground,
33 | foreground2: this.state.separateForeground
34 | ? this.randomColor().foreground
35 | : foreground,
36 | })
37 | }
38 |
39 | onSizeChange = size => {
40 | this.setState({
41 | size: size.target.value,
42 | })
43 | }
44 |
45 | onSeparateForeground = () => {
46 | this.setState({
47 | separateForeground: !this.state.separateForeground,
48 | })
49 | }
50 |
51 | onBackgroundChange = color => {
52 | this.setState({
53 | background: color.hex,
54 | })
55 | }
56 |
57 | onForegroundChange = color => {
58 | this.setState({
59 | foreground: color.hex,
60 | })
61 |
62 | if (!this.state.separateForeground) {
63 | this.setState({
64 | foreground2: color.hex,
65 | })
66 | }
67 | }
68 |
69 | onForeground2Change = color => {
70 | this.setState({
71 | foreground2: color.hex,
72 | })
73 | }
74 |
75 | render() {
76 | return (
77 |
78 |
VSCode icon generator
79 |
80 |
93 |
,
104 | ),
105 | ).toString('base64')}`}
106 | download="icon.svg"
107 | title="icon.svg"
108 | >
109 |
Download SVG icon
110 |
111 |
112 |
113 |
119 |
120 |
121 | )
122 | }
123 | }
124 |
125 | export default App
126 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/ControlsRenderer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { SketchPicker } from 'react-color'
3 | import COLORS from './material-colors.json'
4 |
5 | class ControlsRenderer extends React.Component {
6 | constructor(props) {
7 | super(props)
8 | this.state = {
9 | displayBackground: false,
10 | displayForeground: false,
11 | displayForeground2: false,
12 | }
13 | }
14 |
15 | displayBackground = () => {
16 | this.setState({ displayBackground: !this.state.displayBackground })
17 | }
18 |
19 | displayForeground = () => {
20 | this.setState({ displayForeground: !this.state.displayForeground })
21 | }
22 |
23 | displayForeground2 = () => {
24 | this.setState({ displayForeground2: !this.state.displayForeground2 })
25 | }
26 |
27 | handleClose = () => {
28 | this.setState({
29 | displayBackground: false,
30 | displayForeground: false,
31 | displayForeground2: false,
32 | })
33 | }
34 |
35 | renderColorPicker = (
36 | color,
37 | isForeground,
38 | colorHandler,
39 | clickHandler,
40 | displayed,
41 | ) => {
42 | return (
43 |
44 |
52 | {displayed ? (
53 |
54 |
55 |
color[isForeground ? 'foreground' : 'background'],
58 | )}
59 | color={color}
60 | onChange={colorHandler}
61 | disableAlpha
62 | />
63 |
64 | ) : null}
65 |
66 | )
67 | }
68 |
69 | render() {
70 | const {
71 | onForegroundChange,
72 | onForeground2Change,
73 | onBackgroundChange,
74 | onSizeChange,
75 | onSeparateForeground,
76 | onRandom,
77 | background,
78 | foreground,
79 | foreground2,
80 | separateForeground,
81 | size,
82 | } = this.props
83 |
84 | return (
85 |
86 |
87 |
88 |
94 |
95 |
96 | Foreground :
97 | {this.renderColorPicker(
98 | foreground,
99 | true,
100 | onForegroundChange,
101 | this.displayForeground,
102 | this.state.displayForeground,
103 | )}
104 |
105 | {separateForeground ? (
106 |
107 | Foreground 2 :
108 | {this.renderColorPicker(
109 | foreground2,
110 | true,
111 | onForeground2Change,
112 | this.displayForeground2,
113 | this.state.displayForeground2,
114 | )}
115 |
116 | ) : (
117 | ''
118 | )}
119 |
120 | Background :
121 | {this.renderColorPicker(
122 | background,
123 | false,
124 | onBackgroundChange,
125 | this.displayBackground,
126 | this.state.displayBackground,
127 | )}
128 |
129 |
130 | Size:
131 |
138 |
139 |
140 |
141 |
142 |
143 | )
144 | }
145 | }
146 |
147 | export default ControlsRenderer
148 |
--------------------------------------------------------------------------------
/src/IconRenderer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const IconRenderer = props => {
4 | const { background, foreground, foreground2, size } = props
5 | return (
6 |
94 | )
95 | }
96 |
97 | export default IconRenderer
98 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | height: 100vh;
3 | background-color: #2c3e50;
4 | color: #ffffff;
5 | font-family: sans-serif;
6 | }
7 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/src/material-colors.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "foreground": "#f44336",
4 | "background": "#d32f2f"
5 | },
6 | {
7 | "foreground": "#E91E63",
8 | "background": "#C2185B"
9 | },
10 | {
11 | "foreground": "#9C27B0",
12 | "background": "#7B1FA2"
13 | },
14 | {
15 | "foreground": "#673AB7",
16 | "background": "#512DA8"
17 | },
18 | {
19 | "foreground": "#3F51B5",
20 | "background": "#303F9F"
21 | },
22 | {
23 | "foreground": "#2196F3",
24 | "background": "#1976D2"
25 | },
26 | {
27 | "foreground": "#03A9F4",
28 | "background": "#0288D1"
29 | },
30 | {
31 | "foreground": "#00BCD4",
32 | "background": "#0097A7"
33 | },
34 | {
35 | "foreground": "#009688",
36 | "background": "#00796B"
37 | },
38 | {
39 | "foreground": "#4CAF50",
40 | "background": "#388E3C"
41 | },
42 | {
43 | "foreground": "#8BC34A",
44 | "background": "#689F38"
45 | },
46 | {
47 | "foreground": "#CDDC39",
48 | "background": "#AFB42B"
49 | },
50 | {
51 | "foreground": "#FFEB3B",
52 | "background": "#FBC02D"
53 | },
54 | {
55 | "foreground": "#FFC107",
56 | "background": "#FFA000"
57 | },
58 | {
59 | "foreground": "#FF9800",
60 | "background": "#F57C00"
61 | },
62 | {
63 | "foreground": "#FF5722",
64 | "background": "#E64A19"
65 | },
66 | {
67 | "foreground": "#795548",
68 | "background": "#5D4037"
69 | },
70 | {
71 | "foreground": "#9E9E9E",
72 | "background": "#616161"
73 | },
74 | {
75 | "foreground": "#607D8B",
76 | "background": "#455A64"
77 | }
78 | ]
79 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 | } else {
39 | // Is not local host. Just register service worker
40 | registerValidSW(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------