Skip to content

The-Marcy-Lab-School/swe-2-5-solo-project_palette-picker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 

Repository files navigation

2.3.0 - Solo Project: Palette Picker

Getting Started

To work on this project, do not clone this repo and do not fork this project. This repo will just serve as your instructions.

Instead, create a new repository called palette-picker that lives on your own account. When creating the repository, make sure it has the following settings:

  • The name is palette-picker (one "L", two "T"s)
  • It is public
  • It has a README.md

Once you have your repo created, clone it down into your unit-2 directory, and cd into it.

Then, create a Vite project inside called app with the following commands:

npm create vite
# > Project Name: app
# > Select a framework: Vanilla
# > Select a variant: JavaScript
cd app
npm i

Vite will give you a bunch of files that you don't need. You can remove these unnecessary files

# delete these files
rm counter.js javascript.svg

Next, make a src directory for all of our non-configuration code

# make a src directory
mkdir src

# move these files into src
mv main.js src/
mv style.css src/

We leave only the index.html file at the root of the project because it serves as the entry point for the rest of the application.

All future JavaScript and CSS files you create should exist somewhere within src. Feel free to create more folders inside it if you'd like.

Finally, we can edit the provided starter code:

  • Edit the <script> tag in index.html (line 11) so that it references the new location of main.js: "/src/main.js"
  • Empty out the style.css file
  • Empty out the main.js file so that all it does is import style.css

Now you have an empty file structure to begin building in! Add your static (unchanging) HTML elements in the index.html file, styles in the src/styles.css file, and any DOM manipulation code in the main.js file.

Project Description

We're going to be building a palette picker program today. A "color palette" is a set of colors that go well together. We're going to be building a program that allows users to create their own palettes, and save them for later. We'll also be able to delete palettes, and copy the colors to the clipboard.

In real life, design palettes can include dozens of colors to handle all aspects of a website: headings, text, background colors, buttons, links, and so on. Today, we're keeping it simple and only using 3 colors per palette.

When you're done, you should have an app with a form for creating palettes and the palettes displayed beneath it, like this:

palette picker default view

And here it is with more palettes created. You should use flexbox or grid to handle the layout of the palettes.

palette picker multiple rows

User Stories

As always, let's start our journey with the user, what can they actually do with our site?

A user story is a description of what a user would do (ideally) with our website once we're done. We write user stories to help us organize and priorities the features that we want to implement.

There are also technical requirements below (e.g. you must have a form, you must use grid or flexbox, and so on), but thinking about the finished product in terms of our user experience is just as useful, if not more important!

We will write user stores in the format: "a user [what the user can do]"

A user:

  • Can create a palette by filling out a form
  • Can provide their palette with a title, choose three colors, and a palette "temperature"
  • Can't submit a form without giving it a title
  • Can visually choose their colors using a color picker
  • Can see all the palettes they create in the palettes section of the page
  • Is provided with 3 default palettes the first time they visit the site (or if they delete all their palettes)
  • Can see their colors with a black and white text example overlaid on each color
  • Can see their colors with a black and white border around each one
  • Can see the temperature of each palette in a banner along the bottom of each one
  • Can click a button next to any color to copy the hex code to their clipboard (#ffffff for example)
  • Can click the copy button and see the text change to "Copied hex!" for 1 second before switching back
  • Can delete a palette they don't like by clicking the delete button
  • Has their palettes saved so even if they close the site, upon returning they can see their palettes

Here are some close ups and examples of what we're looking for:

palettes

Here's the color picker:

palettes

Tech Tips

This is a big project, so here are some helpful things for you to consider. Also, keep in mind you can look at the rubric at the end as a sort of guide to what you need to do.

HTML

Data attributes

Some things in this project get way easier if you know what a data- attribute is and why you'd likely want them on buttons. If you are unfamiliar with data attributes in html and dataset in JS, make sure you read up on them (your DOM assignments used them!).

Color inputs

You know how there's a ton of input types? Check out input type="color" for this project! Read up on how the value of a color input is returned.

Required fields

Do you know how to make an HTML form treat an input as required? It's not hard, try figuring it out, and make sure the text input is required!

JavaScript

Organization

We recommend that you store all .js and .css files in an app/src/ directory, leaving only the index.html file and configuration files in the root of your app/ directory.

Within src/, we recommend that break up your application into separate files that each handle a single responsibility. The recommended files are:

  • local-storage.js - contains helpers for managing local storage (feel free to copy the starter code we've provided in this repo)
  • dom-helpers.js - contains helpers for manipulating the DOM
  • main.js - contains the main logic that sets up event handlers and executes initialization functions.

esModules

Remember, Vite doesn't use commonjs modules like node.

Here's a crash course on esmodules if you need it.

Honestly though, to start it's a real simple notation change:

// commonjs default import
const library = require('library-name');
const localModule = require('./local-module');

// esmodules default import
import library from 'library-name';
import localModule from './local-module';


// commonjs named import
const { namedThing } = require('library-name');
const { namedLocal } = require('./local-module');

// esmodules named import
import { namedThing } from 'library-name';
import { namedLocal } from './local-module';

// esmodules named import with alias
const { namedThing as alias } = require('library-name');

// common js default export
module.exports = namedThing;

// esmodules default export
export default namedThing;

// commonjs named export
module.exports = { namedThing };

// esmodules named export:
// - each one
export const thing = () => {}
export const otherThing = () => {}
// or all together
export {
  thing2,
  otherThing2
}

There are a few more bells and whistles but that's honestly all you need.

Also, what's super cool with Vite is that you can load in some style files in your JS instead of with your html. So don't panic when you see

import './styles.css';

palettes.json

To start, we're giving you the data for 3 palettes in a json format. In your own repo, create a palettes.json file and copy the data below into it.

{
  "5affd4e4-418d-4b62-beeb-1c0f7aaff753": {
    "uuid": "5affd4e4-418d-4b62-beeb-1c0f7aaff753",
    "title": "Marcy",
    "colors": [
      "#c92929",
      "#2f5a8b",
      "#327a5f"
    ],
    "temperature": "neutral"
  },
  "32521ef4-d64c-4906-b06d-f3d0d6b16e0f": {
    "uuid": "32521ef4-d64c-4906-b06d-f3d0d6b16e0f",
    "title": "Sleek and Modern",
    "colors": [
      "#3A5199",
      "#2F2E33",
      "#D5D6D2"
    ],
    "temperature": "cool"
  },
  "8b144d62-faa7-4226-87e1-096d7c1bedc7": {
    "uuid": "8b144d62-faa7-4226-87e1-096d7c1bedc7",
    "title": "Winter Reds",
    "colors": [
      "#A10115",
      "#C0B2B5",
      "#600A0A"
    ],
    "temperature": "warm"
  }
}

Thanks to ES6 modules and Vite, you can just use import to import this object of objects into your code.

import palettes from './palettes.json'
console.log(palettes); // It's now regular JS code!

Pretty cool right? The only catch is you must specify the file type .json. Use the data in this file to generate your default palettes.

UUIDs

This data is organized as an object of objects. This is a common strategy! Each object represents the data for an individual palette. The key to access each object is the object's universally unique id (uuid). That uuid is also stored inside of each object.

Though it's a bit overkill for this project, it is a good practice to use UUIDs to organize data. In particular, it makes finding and deleting individual entries much more efficient. To generate your own UUID values, we'll use the uuid npm package:

npm i uuid

Then, we'll import the v4() function from uuid, renaming it to generateUUID. Whenever you need a new UUID you can just invoke that function:

import { v4 as generateUUID } from 'uuid';

const newPaletteID = generateUUID();

Saving to localStorage

We do not want to use sessionStorage that's different!

We want our palettes to persist across sessions. We don't need databases to do this, assuming we're ok with only saving the data to the user's browser. Here's an article explaining localStorage

Once you understand the basics of localStorage, you can make some helper functions like:

  • setLocalStorageKey(key, value) - This is a wrapper that automatically stringifies the value and sets it to the key

    const setLocalStorageKey = (key, value) => {
      localStorage.setItem(key, JSON.stringify(value));
    }
  • getLocalStorageKey(key) - This is a wrapper that automatically parses the value and returns it, but also handles the errors (JSON.parse should always be wrapped in a try/catch since it breaks so easily). If there's an error it console.errors it and returns null

    const getLocalStorageKey = (key) => {
      const storedValue = localStorage.getItem(key);
      return JSON.parse(storedValue);
    }

With those two out of the way, it is recommended that you make some more focused helper functions like:

  • setPalettes(newPalettes)
    • Replace whatever palettes are saved in localStorage with the provided object of newPalettes
  • getPalettes()
    • Get the palettes object stored in localStorage Always return an object, either full of palettes or empty. If it always returns an object, it will make the code that uses this function simpler.
  • initPalettesIfEmpty()
    • This one is important! If you don't have any palettes on page load, then you should add the default palettes to localStorage. To be clear, that's on page load, not immediately following the event that they delete all of the palettes. So if the user deletes each palette, only if they refresh the page, the defaults will appear
  • addPalette(newPalette)
    • Add the palette to your saved localStorage palettes. First retrieve the existing palettes, add the new palette to the object, and then set the palettes again.
  • removePalette(paletteUuid)
    • Remove the palette from your saved localStorage palettes as found by the palette's uuid. First retrieve the existing palettes, find and remove the specified palette from the object, and then set the palettes again.

Remember these functions are all only the data layer of our project. None of them should be touching the DOM, that's the job of other rendering functions. For example, removePalette() should only remove the palette from the localStorage object, do not try to remove it from the DOM in this function.

Copying to the clipboard

This used to be a pain, but now it's not! Check out this article explaining how to copy with the clipboard API. This is a crucial feature, don't forget it!

And don't forget that users need some confirmation of a copy, so alter the buttons text for a second to say "Copied hex!" for 1 second before switching back. Remember setTimeout?

Tech Rubric

In order to see how well you're doing with this project, here are all the things we need would like to see from you. If you get all of these, then you know that you're where you need to be!

Layout: Structure

  • There is a single main element on the page
  • There is a single h1 element on the page
  • There is a form
  • The form has an h2 label
  • The form has an text input and label for the palette title
  • The form has 3 color type inputs and labels for the color inputs
  • The form has a fieldset with a legend for the temperature setting
  • The form has 3 radio inputs and labels for the temperature setting
  • The form has neutral as the default temperature setting
  • The form has a button to submit the form
  • There is a section for the palettes
  • There is an h2 showing the palettes section
  • The page has a ul and li items that show each palette
  • Each palette has the 3 colors clearly visible somehow
  • Each palette has white and black text overlaid on each of the colors
  • Each palette somehow has white and black border on each of the colors
  • Each palette has 3 copy buttons that show the name of the color they would copy
  • Each palette has a delete button
  • Each palette has a banner along the bottom with the name of the temperature
  • Each palette has a banner along the bottom that is colored by the temperature
    • (gray = neutral, red = warm, blue = cool)
  • Palettes appear next to each other in an organized, responsive, well-spaced layout (flex or grid presentations fine)

layout: Accessibility

  • The form has an aria-label or aria-labelledby attribute that describes the form
  • The section has an aria-label or aria-labelledby attribute that describes the section
  • There are no instances of recreating any semantic elements

Functionality

  • The title is a required field, and the form cannot be submitted without it
  • Clicking the form submit button does not reload the page because the default behavior is prevented
  • Clicking the form submit button creates a new palette in the palettes section
  • Clicking the form submit button clears the form
  • Clicking one of the copy buttons copies the hex code of the color to the clipboard
  • Clicking the copy button copies the selected color to the user's clipboard
  • Clicking the copy button alters the text for a second to say "Copied hex!" for 1 second before switching back
  • Clicking the delete button removes the palette from the page
  • Clicking the delete button removes the palette from localStorage (does not come back upon reload of page)
  • On first visit to the page, there are 3 default palettes
  • If a user deletes all their palettes, on next reload, the default palettes appear again
  • A user's palettes are saved to localStorage

Meta

  • The project is created using Vite
  • The code exists in more than one JS file
  • The project is deployed via GitHub Pages properly
  • The palettes.json file is read properly
  • css flexbox or grid was used
  • The code does not render unescaped text directly to the DOM (createElement or other escape method used)
  • .innerHTML or createElement/.append is used properly at some point in the project
  • .innerHTML or .remove() is used to delete elements from the DOM.
  • The setTimeout method is used to rewrite the copy button text

About

2.3.0 Solo Project - Palette Picker

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •