├── public ├── favicon.ico ├── img │ ├── loading.gif │ ├── arrow.svg │ ├── nfl │ │ ├── dallas-cowboys.svg │ │ ├── green-bay-packers.svg │ │ ├── washington-commanders.svg │ │ ├── los-angeles-chargers.svg │ │ ├── chicago-bears.svg │ │ ├── houston-texans.svg │ │ ├── cincinnati-bengals.svg │ │ ├── arizona-cardinals.svg │ │ ├── new-york-giants.svg │ │ ├── seattle-seahawks.svg │ │ ├── indianapolis-colts.svg │ │ ├── denver-broncos.svg │ │ ├── san-francisco-49ers.svg │ │ ├── atlanta-falcons.svg │ │ ├── new-orleans-saints.svg │ │ ├── new-england-patriots.svg │ │ ├── tennessee-titans.svg │ │ ├── new-york-jets.svg │ │ ├── baltimore-ravens.svg │ │ ├── los-angeles-rams.svg │ │ ├── buffalo-bills.svg │ │ └── pittsburgh-steelers.svg │ ├── nhl │ │ ├── tampa-bay-lightning.svg │ │ ├── montreal-canadiens.svg │ │ ├── vegas-golden-knights.svg │ │ ├── winnipeg-jets.svg │ │ ├── carolina-hurricanes.svg │ │ ├── new-jersey-devils.svg │ │ ├── minnesota-wild.svg │ │ ├── philadelphia-flyers.svg │ │ ├── st-louis-blues.svg │ │ ├── columbus-blue-jackets.svg │ │ ├── calgary-flames.svg │ │ ├── florida-panthers.svg │ │ ├── boston-bruins.svg │ │ ├── arizona-coyotes.svg │ │ ├── new-york-rangers.svg │ │ └── washington-capitals.svg │ ├── mlb │ │ ├── cleveland-indians.svg │ │ ├── detroit-tigers.svg │ │ ├── arizona-diamondbacks.svg │ │ ├── san-diego-padres.svg │ │ ├── pittsburgh-pirates.svg │ │ ├── chicago-cubs.svg │ │ ├── los-angeles-angels-of-anaheim.svg │ │ ├── cincinnati-reds.svg │ │ ├── boston-red-sox.svg │ │ ├── houston-astros.svg │ │ └── miami-marlins.svg │ ├── leagues │ │ ├── nba.svg │ │ └── nfl.svg │ ├── mls │ │ ├── vancouver-whitecaps-fc.svg │ │ ├── fc-dallas.svg │ │ └── portland-timbers.svg │ └── nba │ │ └── phoenix-suns.svg ├── manifest.json ├── styles │ └── reset.css └── index.html ├── sketch ├── epl.sketch ├── mlb.sketch ├── mls.sketch ├── nba.sketch ├── nfl.sketch ├── nhl.sketch └── leagues.sketch ├── netlify.toml ├── src ├── utils │ ├── debounce.js │ ├── uniq.js │ ├── convertNameToId.js │ └── rgbHexConversion.js ├── components │ ├── TeamList.js │ ├── TeamListItem.js │ ├── Static.js │ ├── TeamFilters.js │ └── App.js └── index.js ├── .gitignore ├── package.json ├── scripts └── generateStatic.js └── README.md /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /sketch/epl.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/epl.sketch -------------------------------------------------------------------------------- /sketch/mlb.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/mlb.sketch -------------------------------------------------------------------------------- /sketch/mls.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/mls.sketch -------------------------------------------------------------------------------- /sketch/nba.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/nba.sketch -------------------------------------------------------------------------------- /sketch/nfl.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/nfl.sketch -------------------------------------------------------------------------------- /sketch/nhl.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/nhl.sketch -------------------------------------------------------------------------------- /sketch/leagues.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/sketch/leagues.sketch -------------------------------------------------------------------------------- /public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimniels/teamcolors/HEAD/public/img/loading.gif -------------------------------------------------------------------------------- /public/img/arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | base = "" 3 | publish = "build" 4 | command = "yarn build" 5 | 6 | [[redirects]] 7 | from = "https://teamcolors.netlify.com/*" 8 | to = "https://teamcolors.jim-nielsen.com/:splat" 9 | status = 301 10 | force = true -------------------------------------------------------------------------------- /src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | export default function debounce(fn, delay) { 2 | var timer = null 3 | return function () { 4 | var context = this, args = arguments 5 | clearTimeout(timer) 6 | timer = setTimeout(function () { 7 | fn.apply(context, args) 8 | }, delay) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/utils/uniq.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Take an array of items and return the same array with unique values only 3 | * [1,2,3,3] -> [1,2,3] 4 | */ 5 | export default function uniq(array) { 6 | return array.reduce((acc, item) => { 7 | return acc.includes(item) ? acc : acc.concat(item); 8 | }, []); 9 | } 10 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/utils/convertNameToId.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert Name to ID 3 | * Take a string (usually a team name) with spaces and mixed casing, 4 | * convert it to a lowercased, hyphen-separated string representing an ID 5 | * 6 | * @param {string} name 7 | * @returns {string} id 8 | */ 9 | export default function convertNameToId(name) { 10 | return name.replace(/\s+/g, '-').toLowerCase() 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "teamcolors", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "fuzzy": "^0.1.3", 7 | "react": "^16.5.2", 8 | "react-dom": "^16.5.2", 9 | "react-scripts": "2.0.5" 10 | }, 11 | "scripts": { 12 | "start": "react-scripts start", 13 | "build": "react-scripts build", 14 | "test": "react-scripts test", 15 | "eject": "react-scripts eject" 16 | }, 17 | "eslintConfig": { 18 | "extends": "react-app" 19 | }, 20 | "browserslist": [ 21 | ">0.2%", 22 | "not dead", 23 | "not ie <= 11", 24 | "not op_mini all" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /scripts/generateStatic.js: -------------------------------------------------------------------------------- 1 | // Support ES6, React for imported files 2 | require('babel-core/register')({ 3 | presets: ['es2015', 'react'] 4 | }) 5 | 6 | // Dependencies 7 | var fs = require('fs') 8 | var React = require('react') 9 | var ReactDOMServer = require('react-dom/server') 10 | var Static = require('./components/Static') 11 | var data = require('../../static/data/teams.json') 12 | 13 | // Render static markup from component 14 | var html = ReactDOMServer.renderToStaticMarkup(React.createElement( 15 | Static, 16 | {teams: data.teams} 17 | )) 18 | 19 | // Write to file 20 | fs.writeFileSync('indexStatic.html', html) 21 | -------------------------------------------------------------------------------- /public/img/nfl/dallas-cowboys.svg: -------------------------------------------------------------------------------- 1 | dallas-cowboys -------------------------------------------------------------------------------- /public/img/nhl/tampa-bay-lightning.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/TeamList.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { array, object } from "prop-types"; 3 | import TeamListItem from "./TeamListItem.js"; 4 | 5 | export default class TeamList extends Component { 6 | static propTypes = { 7 | teams: array.isRequired, 8 | activeFilters: object.isRequired 9 | }; 10 | 11 | render() { 12 | const { activeFilters, teams } = this.props; 13 | 14 | return ( 15 |
16 | 29 |
30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/img/nfl/green-bay-packers.svg: -------------------------------------------------------------------------------- 1 | green-bay-packers -------------------------------------------------------------------------------- /public/img/mlb/cleveland-indians.svg: -------------------------------------------------------------------------------- 1 | cleveland-indians -------------------------------------------------------------------------------- /public/img/nfl/washington-commanders.svg: -------------------------------------------------------------------------------- 1 | washington-commanders -------------------------------------------------------------------------------- /public/styles/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td, 15 | article, aside, canvas, details, embed, 16 | figure, figcaption, footer, header, hgroup, 17 | menu, nav, output, ruby, section, summary, 18 | time, mark, audio, video { 19 | margin: 0; 20 | padding: 0; 21 | border: 0; 22 | font-size: 100%; 23 | font: inherit; 24 | vertical-align: baseline; 25 | } 26 | /* HTML5 display-role reset for older browsers */ 27 | article, aside, details, figcaption, figure, 28 | footer, header, hgroup, menu, nav, section { 29 | display: block; 30 | } 31 | body { 32 | line-height: 1; 33 | } 34 | ol, ul { 35 | list-style: none; 36 | } 37 | blockquote, q { 38 | quotes: none; 39 | } 40 | blockquote:before, blockquote:after, 41 | q:before, q:after { 42 | content: ''; 43 | content: none; 44 | } 45 | table { 46 | border-collapse: collapse; 47 | border-spacing: 0; 48 | } 49 | -------------------------------------------------------------------------------- /public/img/nfl/los-angeles-chargers.svg: -------------------------------------------------------------------------------- 1 | san-diego-chargers -------------------------------------------------------------------------------- /public/img/mlb/detroit-tigers.svg: -------------------------------------------------------------------------------- 1 | detroit-tigers -------------------------------------------------------------------------------- /public/img/nfl/chicago-bears.svg: -------------------------------------------------------------------------------- 1 | chicago-bears -------------------------------------------------------------------------------- /public/img/mlb/arizona-diamondbacks.svg: -------------------------------------------------------------------------------- 1 | arizona-diamondbacks -------------------------------------------------------------------------------- /public/img/nhl/montreal-canadiens.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/mlb/san-diego-padres.svg: -------------------------------------------------------------------------------- 1 | san-diego-padres -------------------------------------------------------------------------------- /src/components/TeamListItem.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { object } from "prop-types"; 3 | 4 | export default class TeamListItem extends Component { 5 | static propTypes = { 6 | team: object.isRequired, 7 | activeFilters: object.isRequired 8 | }; 9 | 10 | /** 11 | * Handle Color click 12 | * Select all text when color values are clicked/tapped 13 | * 14 | * {@link http://stackoverflow.com/questions/6139107/programatically-select-text-in-a-contenteditable-html-element} 15 | */ 16 | handleColorClick = e => { 17 | const range = document.createRange(); 18 | range.selectNodeContents(e.target); 19 | const sel = window.getSelection(); 20 | sel.removeAllRanges(); 21 | sel.addRange(range); 22 | }; 23 | 24 | render() { 25 | const { 26 | team, 27 | activeFilters: { color: activeColor } 28 | } = this.props; 29 | 30 | return ( 31 |
  • 32 |

    38 | {team.name} 39 |

    40 | 55 |
  • 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/utils/rgbHexConversion.js: -------------------------------------------------------------------------------- 1 | /** 2 | * RGB To HEX 3 | * Convert a space delimited string of RGB values to HEX values 4 | * 5 | * @param {string} rgb - Space delimited RGB color value, i.e. "0 0 0" 6 | * @returns {string} - HEX color value 7 | */ 8 | export function rgbToHex(str) { 9 | // Split RGB str into individual pieces and convert to int 10 | var rgb = str.split(" "); 11 | var r = parseInt(rgb[0]); 12 | var g = parseInt(rgb[1]); 13 | var b = parseInt(rgb[2]); 14 | 15 | // Then convert RGB to HEX 16 | // http://stackoverflow.com/questions/1133770/how-do-i-convert-a-string-into-an-integer-in-javascript 17 | function componentToHex(c) { 18 | var hex = c.toString(16).toUpperCase(); 19 | // eslint-disable-next-line 20 | return hex.length == 1 ? "0" + hex : hex; 21 | } 22 | 23 | // Return i.e. '34AB32' 24 | return componentToHex(r) + componentToHex(g) + componentToHex(b); 25 | } 26 | 27 | /** 28 | * HEX to RGB 29 | * Convert a HEX value to a space delimited string of RGB values 30 | * 31 | * @param {string} hex - Hex color value (supports inclusin of '#' symbol) 32 | * @returns {string} - Space delimited string of RGB values 33 | */ 34 | export function hexToRgb(hex) { 35 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") 36 | var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; 37 | hex = hex.replace(shorthandRegex, function(m, r, g, b) { 38 | return r + r + g + g + b + b; 39 | }); 40 | 41 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 42 | // returns space separated RGB values, i.e. "123 40 51" 43 | return result 44 | ? parseInt(result[1], 16) + 45 | " " + 46 | parseInt(result[2], 16) + 47 | " " + 48 | parseInt(result[3], 16) 49 | : null; 50 | } 51 | -------------------------------------------------------------------------------- /public/img/nfl/houston-texans.svg: -------------------------------------------------------------------------------- 1 | houston-texans -------------------------------------------------------------------------------- /public/img/nhl/vegas-golden-knights.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/cincinnati-bengals.svg: -------------------------------------------------------------------------------- 1 | cincinnati-bengals -------------------------------------------------------------------------------- /src/components/Static.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | var StaticHtml = React.createClass({ 4 | PropTypes: { 5 | teams: React.PropTypes.array.isRequired 6 | }, 7 | 8 | render: function() { 9 | const { teams } = this.props 10 | 11 | return ( 12 | 13 | 14 | 15 | TeamColors: Find and copy color values from your favorite sports teams. 16 | 17 | 18 | 19 | 20 |

    21 | TeamColors: Find and copy color values from your favorite sports teams. 22 |

    23 |

    24 | For an interactive version of this site, click here. 25 |

    26 | 61 | 62 | 63 | ) 64 | } 65 | }) 66 | 67 | module.exports = StaticHtml 68 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TeamColors: Find and copy color values from your favorite sports teams. 5 | 6 | 7 | 8 | 9 | 10 | 11 |
    12 |
    13 |

    14 | 15 | TeamColors logo 16 | 17 |

    18 |

    19 | 20 | A project from Jim Nielsen. Got suggestions or corrections? Source is on Github. 21 | 22 | 23 | Note: some colors are official, others are approximations. Learn more. 24 | 25 |

    26 |
    27 |
    28 | 29 |
    30 |
    31 |

    32 | Loading... Not loading? You’re probably on an old browser or have Javascript disabled. You can still view the raw data. 33 |

    34 |
    35 |
    36 | 37 | 38 | 49 | 50 | -------------------------------------------------------------------------------- /public/img/nfl/arizona-cardinals.svg: -------------------------------------------------------------------------------- 1 | arizona-cardinals -------------------------------------------------------------------------------- /public/img/nhl/winnipeg-jets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/new-york-giants.svg: -------------------------------------------------------------------------------- 1 | new-york-giants -------------------------------------------------------------------------------- /public/img/mlb/pittsburgh-pirates.svg: -------------------------------------------------------------------------------- 1 | pittsburgh-pirates -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import uniq from "./utils/uniq.js"; 4 | import App from "./components/App.js"; 5 | import convertNameToId from "./utils/convertNameToId.js"; 6 | import { rgbToHex, hexToRgb } from "./utils/rgbHexConversion.js"; 7 | import json from "./teams.json"; 8 | 9 | // Massage the team data as needed 10 | const teams = massageTeamsData(json); 11 | 12 | // Render the App 13 | ReactDOM.render( 14 | , 22 | document.getElementById("root") 23 | ); 24 | 25 | /** 26 | * Massage JSON by looping through all the teams and: 27 | * 1. Add a team ID 28 | * 2. If there's no HEX, convert the RGB to HEX and add it 29 | * 3. If there's no RGB, convert the HEX to RGB and add it 30 | * 4. Sort by team id 31 | * 32 | * @param {Object[]} - Original JSON values of teams 33 | * @return {Object[]} - Modified to include `id` and `hex` or `rgb` key/value 34 | * pairs (if missing) and sorted by team `id` 35 | */ 36 | function massageTeamsData(data) { 37 | let out = data.map(team => { 38 | team.id = convertNameToId(team.name); 39 | if (!team.colors.hex) { 40 | team.colors.hex = team.colors.rgb.map(color => rgbToHex(color)); 41 | } 42 | if (!team.colors.rgb) { 43 | team.colors.rgb = team.colors.hex.map(color => hexToRgb(color)); 44 | } 45 | 46 | return team; 47 | }); 48 | 49 | out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)); 50 | 51 | return out; 52 | } 53 | 54 | /** 55 | * Pluck out a unique list of leagues from the team data 56 | * @param {Object[]} - List of all teams 57 | * @return {Array.} - List of leagues 58 | */ 59 | function getLeagues(teams) { 60 | return uniq(teams.map(team => team.league)); 61 | } 62 | 63 | /** 64 | * Pluck out a unique list of color modes from the team data 65 | * @param {Object[]} - List of all teams 66 | * @return {Array.} - List of leagues 67 | */ 68 | function getColors(teams) { 69 | return uniq( 70 | teams.map(team => Object.keys(team.colors)).reduce((a, b) => a.concat(b)) 71 | ); 72 | } 73 | 74 | /** 75 | * Generate a unique list of leagues from the team data 76 | * Object mapping color support 77 | */ 78 | function getColorsByLeague(teams) { 79 | let colorsByLeague = {}; 80 | teams.forEach(({ colors, league }) => { 81 | if (!colorsByLeague[league]) { 82 | colorsByLeague[league] = Object.keys(colors); 83 | } 84 | }); 85 | return colorsByLeague; 86 | } 87 | -------------------------------------------------------------------------------- /public/img/nfl/seattle-seahawks.svg: -------------------------------------------------------------------------------- 1 | seattle-seahawks -------------------------------------------------------------------------------- /public/img/nhl/carolina-hurricanes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/mlb/chicago-cubs.svg: -------------------------------------------------------------------------------- 1 | chicago-cubs -------------------------------------------------------------------------------- /public/img/nfl/indianapolis-colts.svg: -------------------------------------------------------------------------------- 1 | indianapolis-colts -------------------------------------------------------------------------------- /public/img/leagues/nba.svg: -------------------------------------------------------------------------------- 1 | nba -------------------------------------------------------------------------------- /public/img/leagues/nfl.svg: -------------------------------------------------------------------------------- 1 | nfl -------------------------------------------------------------------------------- /public/img/nfl/denver-broncos.svg: -------------------------------------------------------------------------------- 1 | denver-broncos -------------------------------------------------------------------------------- /public/img/nfl/san-francisco-49ers.svg: -------------------------------------------------------------------------------- 1 | san-francisco-49ers -------------------------------------------------------------------------------- /public/img/mlb/los-angeles-angels-of-anaheim.svg: -------------------------------------------------------------------------------- 1 | los-angeles-angels-of-anaheim -------------------------------------------------------------------------------- /public/img/nhl/new-jersey-devils.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nhl/minnesota-wild.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/TeamFilters.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { array, func, object } from "prop-types"; 3 | import debounce from "../utils/debounce.js"; 4 | 5 | export default class TeamFilters extends Component { 6 | static propTypes = { 7 | activeFilters: object.isRequired, 8 | leagues: array.isRequired, 9 | colors: array.isRequired, 10 | colorsByLeague: object.isRequired, 11 | onUserInput: func.isRequired 12 | }; 13 | 14 | // Debounce the keyup event 15 | // http://stackoverflow.com/questions/23123138/perform-debounce-in-react-js/24679479#24679479 16 | componentWillMount() { 17 | this.delayedHandleChange = debounce(this.handleChange, 125); 18 | } 19 | 20 | handleKeyUp = e => { 21 | e.persist(); 22 | this.delayedHandleChange(); 23 | }; 24 | 25 | handleChange = () => { 26 | this.props.onUserInput({ 27 | league: this.refs.leagueInput.value, 28 | color: this.refs.colorInput.value, 29 | search: this.refs.searchInput.value 30 | }); 31 | }; 32 | 33 | render() { 34 | const { 35 | leagues, 36 | colors, 37 | colorsByLeague, 38 | activeFilters: { 39 | league: activeLeague, 40 | color: activeColor, 41 | search: activeSearch 42 | } 43 | } = this.props; 44 | 45 | return ( 46 |
    47 |
    48 | 69 | 70 | 95 | 96 | 106 |
    107 |
    108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /public/img/nfl/atlanta-falcons.svg: -------------------------------------------------------------------------------- 1 | atlanta-falcons -------------------------------------------------------------------------------- /public/img/nhl/philadelphia-flyers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/mlb/cincinnati-reds.svg: -------------------------------------------------------------------------------- 1 | cincinnati-reds -------------------------------------------------------------------------------- /public/img/nfl/new-orleans-saints.svg: -------------------------------------------------------------------------------- 1 | new-orleans-saints -------------------------------------------------------------------------------- /public/img/nhl/st-louis-blues.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/new-england-patriots.svg: -------------------------------------------------------------------------------- 1 | new-england-patriots -------------------------------------------------------------------------------- /public/img/mls/vancouver-whitecaps-fc.svg: -------------------------------------------------------------------------------- 1 | vancouver-whitecaps-fc -------------------------------------------------------------------------------- /public/img/mlb/boston-red-sox.svg: -------------------------------------------------------------------------------- 1 | boston-red-sox -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Team Colors 2 | 3 | ![TeamColors screenshot](http://i.imgur.com/XbWE9cG.png) 4 | 5 | [Team Colors](http://jim-nielsen.com/teamcolors) is a reference of HEX, RGB, CMYK, and Pantone color values of major league sports teams. 6 | 7 | ## How-To 8 | 9 | Install: `yarn install` 10 | Development: `yarn start` 11 | Build: `yarn build` 12 | 13 | ## How It Works 14 | 15 | Site is built on the react framework. `index.html` is the shell container for react app. If javascript is not supported, a link is shown to the raw JSON data which has all color information. 16 | 17 | Color data is housed in a single `.json` file `src/teams.json`. Any changes to team colors can be done there. _Note on colors_: Color definitions for each team are in arrays and grouped by color mode. Color values should match index position in the array across color modes, for example: 18 | 19 | ``` 20 | colors: 21 | rgb: TEAMS-RGB-BLUE, TEAMS-RGB-RED 22 | hex: TEAMS-HEX-BLUE, TEAMS-HEX-RED 23 | ``` 24 | 25 | Source artwork for each team is grouped by league in `sketch`. Production versions of these logo should be in `.svg` format in `public/img`. 26 | 27 | ### Edit Team Color or Name 28 | 29 | Find teams `.json` file in `src/teams.json`, and edit the info you need. 30 | 31 | ### Add a Team 32 | 33 | 1. Determine the team’s league 34 | 2. Following the established pattern, add the team’s name and colors the `.json` file 35 | 3. Add a vector logo for the team in its corresponding `.sketch` league file in `sketch` with the team’s name (as referenced in its `.json` file) in lowercase with hyphens, i.e. "utah-jazz" 36 | 4. Export the team’s `.svg` logo to `public/img/` 37 | 5. Preferably, optimize the svg (with a tool like [SVGO](https://github.com/svg/svgo)) 38 | 6. Run `yarn build`, commit, push 39 | 40 | ## Official Color References 41 | 42 | ### NBA 43 | 44 | All NBA colors are official ([source](http://courtside.nba.com/QuickPlace/nbalogo/Main.nsf/$defaultview/AD4C002C7D0F37A285257D660058EAED/$File/NBA%20Primary%20Composite_14-15PLAYOFFS.pdf?OpenElement) user & pass: nbamedia). 45 | 46 | The NBA only provides RGB, CMYK, and Pantone colors for each team, so the HEX color is a programmatic conversion of the RGB color. 47 | 48 | ### NFL 49 | 50 | All NFL colors are official (see sources below). 51 | 52 | The NFL provides official RGB, HEX, CMYK, and Pantone colors (so none of the colors you see on Team Colors are conversions). 53 | 54 | The NFL has logo slicks which detail team color values. These are provided on a per-conference basis. _Note_: each of these source links are over 100MB in size, so they take a while to download. 55 | 56 | - [AFC North](http://www.nflmedia.com/afc_north.zip) 57 | - [AFC South](http://www.nflmedia.com/afc_south.zip) 58 | - [AFC East](http://www.nflmedia.com/afc_east.zip) 59 | - [AFC West](http://www.nflmedia.com/afc_west.zip) 60 | - [NFC North](http://www.nflmedia.com/nfc_north.zip) 61 | - [NFC South](http://www.nflmedia.com/nfc_south.zip) 62 | - [NFC East](http://www.nflmedia.com/nfc_east.zip) 63 | - [NFC West](http://www.nflmedia.com/nfc_west.zip) 64 | 65 | ### MLB 66 | 67 | MLB colors have been extracted from the official “RGB Digital Art” spot color logo slicks provided at [MLB Press Box](http://mlbpressbox.mlbstyleguide.com) (user account required). They were not explicitly stated values, but they are color values pulled from individual team logos in an _official_ MLB document. 68 | 69 | The extracted colors are in HEX form and their RGB counterparts are generated programmatically. 70 | 71 | - [American League logo slick](http://i.imgur.com/RP5kBSI.png) 72 | - [National League logo slick](http://i.imgur.com/FcuizSx.png) 73 | 74 | ### NHL 75 | 76 | NHL colors are official. As per [Michael Sharer](https://github.com/epitaphmike) of the NHL. 77 | 78 | ### MLS 79 | 80 | MLS colors are currently approximations, with the exceptions listed below. I am working on getting official colors of the remaining teams. 81 | 82 | - [Philadelphia Union](http://portfolios.scad.edu/gallery/36587433/Philadelphia-Union-Brand-Guidelines) 83 | 84 | ### EPL 85 | 86 | These leagues’ teams and colors are currently approximations. I am working on getting official colors. If you know how/where to find them, please open an issue here in Github. 87 | 88 | ## To-Dos 89 | 90 | - [ ] Switch to `flex` for layout 91 | - [ ] Improve filtering with fuzzy string search 92 | - [ ] Improve error states for when data doesn't render 93 | - [ ] Consider alternatives to no-js users rather than just "here's the raw data" (something that doesn't required a build if a single color in the JSON file is changed) 94 | - [ ] Possibly add team `id` manually to JSON file ?? 95 | -------------------------------------------------------------------------------- /public/img/nfl/tennessee-titans.svg: -------------------------------------------------------------------------------- 1 | tennessee-titans -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import { array, object, number, string } from "prop-types"; 3 | import fuzzy from "fuzzy"; 4 | import TeamList from "./TeamList.js"; 5 | import TeamFilters from "./TeamFilters.js"; 6 | 7 | export default class App extends Component { 8 | static propTypes = { 9 | teams: array.isRequired, 10 | leagues: array.isRequired, 11 | colors: array.isRequired, 12 | colorsByLeague: object.isRequired, 13 | threshold: number.isRequired, 14 | initialColor: string, 15 | initialLeague: string, 16 | initialSearch: string 17 | }; 18 | 19 | constructor(props) { 20 | super(props); 21 | 22 | // @TODO Add ability to pass these initial state via the URL 23 | // Intial filters 24 | const activeFilters = { 25 | color: props.initialColor || "", 26 | league: props.initialLeague || "", 27 | search: props.initialSearch || "" 28 | }; 29 | 30 | // Filter teams by passed in vals 31 | const filteredTeams = this.getFilteredTeams(activeFilters); 32 | 33 | this.state = { 34 | activeFilters: activeFilters, 35 | visibleTeams: filteredTeams.slice(0, props.threshold), 36 | allTeams: filteredTeams 37 | }; 38 | } 39 | 40 | componentDidMount() { 41 | // Handle scroll 42 | // Throttle the scroll event and detect if we're at the bottom of the page 43 | // If we are, show more teams 44 | var throttle = function(fn, threshhold, scope) { 45 | threshhold || (threshhold = 250); 46 | var last, deferTimer; 47 | return function() { 48 | var context = scope || this; 49 | 50 | var now = +new Date(), 51 | args = arguments; 52 | if (last && now < last + threshhold) { 53 | // hold on to it 54 | clearTimeout(deferTimer); 55 | deferTimer = setTimeout(function() { 56 | last = now; 57 | fn.apply(context, args); 58 | }, threshhold); 59 | } else { 60 | last = now; 61 | fn.apply(context, args); 62 | } 63 | }; 64 | }; 65 | window.onscroll = throttle( 66 | function() { 67 | if (window.innerHeight + window.scrollY >= document.body.offsetHeight) { 68 | this.handleShowMore(); 69 | } 70 | }, 71 | 150, 72 | this 73 | ); 74 | } 75 | 76 | handleShowMore = () => { 77 | const sliceBegin = this.state.visibleTeams.length; 78 | const sliceEnd = sliceBegin + this.props.threshold; 79 | const newTeams = this.state.allTeams.slice(sliceBegin, sliceEnd); 80 | this.setState({ 81 | visibleTeams: this.state.visibleTeams.concat(newTeams) 82 | }); 83 | }; 84 | 85 | // User input filters 86 | handleUserInput = activeFilters => { 87 | const filteredTeams = this.getFilteredTeams(activeFilters); 88 | this.setState({ 89 | activeFilters: activeFilters, 90 | visibleTeams: filteredTeams.slice(0, this.props.threshold), 91 | allTeams: filteredTeams 92 | }); 93 | }; 94 | 95 | // Return an array of teams (filtered if relevant) 96 | getFilteredTeams = activeFilters => { 97 | const { teams } = this.props; 98 | return teams.filter(team => { 99 | if (activeFilters.league !== "") { 100 | if (activeFilters.league !== team.league) { 101 | return false; 102 | } 103 | } 104 | 105 | if (activeFilters.color !== "") { 106 | if (!(activeFilters.color in team.colors)) { 107 | return false; 108 | } 109 | } 110 | 111 | // @TODO possibly fix to fit array of multiple, not single, items 112 | if (activeFilters.search !== "") { 113 | if (fuzzy.filter(activeFilters.search, [team.name]).length === 0) { 114 | return false; 115 | } 116 | } 117 | 118 | return true; 119 | }); 120 | }; 121 | 122 | render() { 123 | const { activeFilters, allTeams, visibleTeams } = this.state; 124 | 125 | const { leagues, colors, colorsByLeague } = this.props; 126 | 127 | return ( 128 |
    129 | 136 | 137 | {visibleTeams.length < allTeams.length ? ( 138 |

    Loading more...

    139 | ) : null} 140 |
    141 | ); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /public/img/nhl/columbus-blue-jackets.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/new-york-jets.svg: -------------------------------------------------------------------------------- 1 | new-york-jets -------------------------------------------------------------------------------- /public/img/nfl/baltimore-ravens.svg: -------------------------------------------------------------------------------- 1 | baltimore-ravens -------------------------------------------------------------------------------- /public/img/nhl/calgary-flames.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/los-angeles-rams.svg: -------------------------------------------------------------------------------- 1 | st-louis-rams -------------------------------------------------------------------------------- /public/img/nhl/florida-panthers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nhl/boston-bruins.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/buffalo-bills.svg: -------------------------------------------------------------------------------- 1 | buffalo-bills -------------------------------------------------------------------------------- /public/img/mls/fc-dallas.svg: -------------------------------------------------------------------------------- 1 | fc-dallas -------------------------------------------------------------------------------- /public/img/mlb/houston-astros.svg: -------------------------------------------------------------------------------- 1 | houston-astros -------------------------------------------------------------------------------- /public/img/mlb/miami-marlins.svg: -------------------------------------------------------------------------------- 1 | miami-marlins -------------------------------------------------------------------------------- /public/img/nhl/arizona-coyotes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nhl/new-york-rangers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nba/phoenix-suns.svg: -------------------------------------------------------------------------------- 1 | phoenix-suns -------------------------------------------------------------------------------- /public/img/mls/portland-timbers.svg: -------------------------------------------------------------------------------- 1 | portland-timbers -------------------------------------------------------------------------------- /public/img/nhl/washington-capitals.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/img/nfl/pittsburgh-steelers.svg: -------------------------------------------------------------------------------- 1 | pittsburgh-steelers --------------------------------------------------------------------------------