8 - Changing Colors
8.1 Changing Colors

Changing colors

We want our users to be able to change the colors of our note cards. To do this we will render out a series of colors within the <Controls/> component, then allow users to click on these colors to update a particular note card.

Color component

Each color will have it's own component: src/components/Color.jsx

Start by creating the following component and adding some functionality so we can see the selected color in the console.

color will be passed down through the <Controls/> component.

Color.jsx
const Color = ({ color }) => {
    const changeColor = () => {
        console.log("CHange color clicked:", color);
    };
 
    return (
        <div
            onClick={changeColor}
            className="color"
            style={{ backgroundColor: color.colorHeader }}
        ></div>
    );
};

Import <Color/> and render out each color one by one while passing down the color object on each iteration.

Controls.jsx
//...
import colors from "../assets/colors.json";
import Color from "./Color";
 
const Controls = () => {
    return (
        <div id="controls">
            <AddButton />
            {colors.map((color) => (
                <Color key={color.id} color={color} />
            ))}
        </div>
    );
};

Styling the <Color/> component

index.css
.color {
    background-color: grey;
    height: 40px;
    width: 40px;
    border-radius: 50%;
 
    cursor: pointer;
    transition: 0.3s;
}
 
.color:hover {
    height: 45px;
    width: 45px;
}

Selected Note

Before we can update a Note color we first need to select a note. A "selected note" can be defined by any note we have actively clicked on or edited.

We'll set our selected note inside of the NoteContext by setting the following state.

Be sure to pass the state and setter method down in contextData so we can access these throught our app.

NotesContext.jsx
const NotesProvider = ({ children }) => {
    const [selectedNote, setSelectedNote] = useState(null);
    //...
    const contextData = {
            //...
            selectedNote, 
            setSelectedNote
        };

There are 2 ways to set a the selectedNote state.

  1. On note header mousedown
  2. On focus, before we begin updating the note text
NoteCard
    //...
    const { setSelectedNote } = useContext(NotesContext);
    const mouseDown = (e) => {
        if (e.target.className === "card-header") {
            //....
            setSelectedNote(note);
        }
    };
 
    //...
 
    <div className="card-body">
        <textarea
            onKeyUp={handleKeyUp}
            onFocus={() => {
                setZIndex(cardRef.current);
                setSelectedNote(note);
            }}

Let's test this out by retreiving the selected note inside of the color component, and consoling it out when the color is clicked.

Color.jsx
const Color = ({ color }) => {
    const {selectedNote} = useContext(NotesContext)
 
    const changeColor = () => {
        console.log("Selected color:", selectedNote);
    };

Handle color change

Once we get access to the selected note we can then update the note color on the frontend as well as in our database by doing the following:

  1. Find where note is in our notes state using the note id
  2. Update our notes state
  3. Sending new colors back to our database for updating.
const changeColor = () => {
    console.log("Selected color:", selectedNote);
 
    try {
        const currentNoteIndex = notes.findIndex(
            (note) => note.$id === selectedNote.$id
        );
 
        const updatedNote = {
            ...notes[currentNoteIndex],
            colors: JSON.stringify(color),
        };
 
        const newNotes = [...notes];
        newNotes[currentNoteIndex] = updatedNote;
        setNotes(newNotes);
 
        db.notes.update(selectedNote.$id, {
            colors: JSON.stringify(color),
        });
    } catch (error) {
        alert("You must select a note before changing colors");
    }
};