├── public
├── robots.txt
├── favicon.ico
├── favicon-16x16.png
├── favicon-32x32.png
├── apple-touch-icon.png
├── icons
│ ├── mstile-150x150.png
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ └── safari-pinned-tab.svg
├── browserconfig.xml
├── manifest.json
└── index.html
├── src
├── vite-env.d.ts
├── components
│ ├── app
│ │ ├── index.ts
│ │ ├── app.scss
│ │ └── app.tsx
│ ├── header
│ │ ├── index.ts
│ │ ├── header-button.tsx
│ │ ├── header-icon.tsx
│ │ ├── header.tsx
│ │ └── header.scss
│ ├── sidebar
│ │ ├── index.ts
│ │ ├── main-menu-item.tsx
│ │ ├── sub-menu.tsx
│ │ ├── sidebar-footer.tsx
│ │ ├── color-history.tsx
│ │ ├── menu-item.tsx
│ │ ├── color-name-menu.tsx
│ │ ├── sidebar.tsx
│ │ ├── sidebar.scss
│ │ └── help-menu.tsx
│ ├── body-content
│ │ ├── index.ts
│ │ ├── body-content.tsx
│ │ └── body-content.scss
│ ├── color-input
│ │ ├── index.ts
│ │ └── color-input.tsx
│ ├── color-square
│ │ ├── index.ts
│ │ ├── color-square.scss
│ │ └── color-square.tsx
│ ├── kofi-button
│ │ ├── index.ts
│ │ └── kofi-button.tsx
│ ├── plus-button
│ │ ├── index.ts
│ │ ├── plus-button.tsx
│ │ └── plus-button.scss
│ └── hamburger-button
│ │ ├── index.ts
│ │ ├── hamburger-button.tsx
│ │ └── hamburger-button.scss
├── styles
│ ├── _general.scss
│ └── _colors.scss
├── types
│ ├── color-name-list.d.ts
│ └── app.ts
├── fonts.ts
├── hooks
│ └── use-online.ts
├── images
│ └── clear-input.svg
├── index.css
├── utils
│ ├── url.ts
│ └── color.ts
├── main.tsx
└── contexts
│ ├── history-context.tsx
│ ├── sidebar-context.tsx
│ ├── split-view-context.tsx
│ └── input-context.tsx
├── .prettierrc.json
├── .firebaserc
├── github
├── ko-fi.png
├── formula.png
└── demo_small.gif
├── tsconfig.json
├── vite.config.ts
├── firebase.json
├── .gitignore
├── tsconfig.node.json
├── .github
└── workflows
│ ├── firebase-hosting-merge.yml
│ └── firebase-hosting-pull-request.yml
├── tsconfig.app.json
├── LICENSE
├── package.json
├── eslint.config.js
├── index.html
└── README.md
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
Generate shades... AND tints of your favorite colors
6 | 7 | 8 | Shade Generator aims to provide a quick and easy way to generate the shades and tints of the colors you use in all of your web development and design projects. 9 | 10 | It's very easy to use. Just enter the color you would like to get shades for (accepts hex, css names, rgb, and more) and the site does the rest. Hover over the shade you want the color code for (or tap on mobile) and click on the format you would like to copy to your clipboard. If you want some inspiration, check out the sidebar where you can see the most popularly used colors as well as a the most recent. You can also view the list of named colors to get a broad range of color inspiration. 11 | 12 |  13 | 14 | ## The Story behind Shade Generator (a.k.a. the boring part) 15 | 16 | Shade generator is a project that started as a codepen a couple years ago. The idea behind it was simple, when you overlap a color with a transparent white or black section, you end up with a tint or shade of that color. As many people do in web development, I would often use this trick to create a contrasting color effect for button hovers or element borders. This got annoying because in order to make the effect work, I would need two elements on the screen for the overlap where I often only needed one. So, I decided to make a little tool to help me find the color codes for this resulting shade by giving me a variety of overlapping icons with the color I was plannibg on using as the background. However it was still not the most convenient because I had to use a chrome plugin called ColorZilla to get the actual code of the resulting color, however I could not think of a better way. Finally, after using this tool hundreds of times I finally thought, there must be some way to calculate this resulting color! 17 | 18 | After a quick google search, I found [this link](https://www.viget.com/articles/equating-color-and-transparency/). I quickly realized calculating the colors I wanted was possible with this very simple formula: 19 | 20 |
21 |
22 |
38 | Shade generator is a project that started as a codepen a couple years 39 | ago. The idea behind it was simple, when you overlap a color with a 40 | transparent white or black section, you end up with a tint or shade of 41 | that color. As many people do in web development, I would often use this 42 | trick to create a contrasting color effect for button hovers or element 43 | borders. This got annoying because in order to make the effect work, I 44 | would need two elements on the screen for the overlap where I often only 45 | needed one. So, I decided to make a little tool to help me find the 46 | color codes for this resulting shade by giving me a variety of 47 | overlapping icons with the color I was plannibg on using as the 48 | background. However it was still not the most convenient because I had 49 | to use a chrome plugin called ColorZilla to get the actual code of the 50 | resulting color, however I could not think of a better way. Finally, 51 | after using this tool hundreds of times I finally thought, there must be 52 | some way to calculate this resulting color! 53 |
54 |55 | After a quick google search, I found{' '} 56 | 61 | this link 62 | 63 | . I immediately realized calculating the colors I wanted was possible 64 | with this very simple formula... 65 |
66 |to be continued...
67 |69 | Throughout the process of making this website, I slowly started adding 70 | in some cool additional features. Some served a purpose, some just for 71 | fun. 72 |
73 |88 | One of the first things I added was the NPM package{' '} 89 | 94 | parse-color 95 | 96 | . It takes a string and parses it for its color values in many 97 | different formats. It can parse colors from hex values, rgb values, 98 | css named colors, and cymk formats. The result is an object that has 99 | the following components: 100 |
101 |114 | This was useful, not only to interpret input from the user but also 115 | for providing hex and rgb values, both of which are important to this 116 | app's functionality. After scrubbing the user input before 117 | passing it to this function, it does a great job of matching 118 | everything you'd expect it to! 119 |
120 |
136 | The next main thing I added was the option to click to copy either the
137 | hex code or the rgb code to your clipboard. The first two things I
138 | tried were document.execCommand("copy") and{' '}
139 | navigator.clipboard.write(). Both of these options worked
140 | but I ran into issued with them working on all devices. I soon
141 | stumbled upon a nice small NPM package called{' '}
142 |
147 | clipboard-polyfill
148 |
149 | . It is nice and compact and gave me a convenient way to ensure
150 | copying would work on all devices and browser the clipboard is
151 | accessible in!
152 |
169 | Now that the basic features were in place, it was time to have some 170 | fun! I decided that the page was a little too plain so I thought I 171 | would add some names for the colors. The first library I added for 172 | this is called{' '} 173 | 178 | color-namer 179 | 180 | . It appealed to me because of the fact that it offered a combination 181 | of multiple lists of colors including CSS colors, X11, Pantone, and 182 | NTC. 183 |
184 |185 | After running into some problems with this package (I can't quite 186 | remember what) I decided to keep looking around. Somehow I missed the 187 | amazing package{' '} 188 | 193 | color-name-list 194 | 195 | . It contains a whopping 18,000+ (and growing) color list which 196 | combines over 15 different sources of color names along with thousands 197 | of user submission. While this list is massive, it still only contains 198 | 0.11% of the total possible RGB combinations so in order to match all 199 | colors so in order to match it to an input color, I used the package{' '} 200 | 205 | nearest-color 206 | 207 | . This matches the color the user enters with the closest color from 208 | the list, and due to the magnitude of color-name-list, it's 209 | usually pretty damn close! 210 |
211 |227 | So now I have the main functionality I want and a little pizzazz, I 228 | realized I needed a faster way to test the app. So I decided the best 229 | way would be to add a random color generator. This may seem like it 230 | should have been an obvious thing to make from the start but it took 231 | me a while to realize it (I know, sometimes I'm thick). It took 232 | me all of 5 minutes to add it and get it going and it made a world of 233 | difference. Now when I'm looking for colors for a new website, 234 | I'll just hit random until something stands out to me. And I 235 | still get a kick out some of these names. 236 |
237 |253 | This was a feature that I added more for the experience than an it 254 | actually providing much value. I had been wanting to mess around with{' '} 255 | 260 | Firebase Firestore 261 | 262 | , Google's real time noSQL database, for a while and this was the 263 | perfect excuse. I added a simple collection for storing the globally 264 | most recent colors that anyone has submitted, updating their timestamp 265 | every time it is used. I could not have been more happy with how easy 266 | it was to set up. It was so fast to set up in fact that I had the 267 | history sidebar up and running in one evening and soon after I added a 268 | section for the most used colors as well. If you are ever interested 269 | in quickly bootstrapping a project that requires storing data, I 270 | highly recommend giving Firebase a shot 271 |
272 |work in progress...
288 |work in progress...
304 |