Year #2, Week #7 đ» đïž
New stuff we learned this week: đ€
CSS Variables
- CSS supports variables. The syntax works like this, you attach variables to a given element (think of this element as being the scope for the variable). The css variable is available then for any descendent of that element. The variable name is declared with two dashes: like so:
.some-element {
--main-bg-color: blue;
}
- Adding this CSS would mean that anywhere within the
.some-element
DOM heirarchy, you could use that variable using thevar()
syntax, like so:
.some-element p {
background-color: var(--main-bg-color);
}
- if you want your variables to be available to the whole page a common best
practice is to attach the variables to the special
:root
psuedo-class like so:
:root {
/* This will be avaialable EVERYWHERE */
--accent-color: hotpink;
}
- the
var()
function also accepts a fallback value, as itâs second argument in case there is no valid variable:
.some-element {
/* will render red if `--main-bg-color` not set */
background-color: var(--main-bg-color, "red");
}
React: Global Keyboard Events
- sometimes we want our websites or web apps to respond to keyboard events at times other than when the user is typing text into a form. Unfortunately, the browser doesnât give us a good way to listen for keyboard events on non-form elements, so the solution is to add a document-level event listener function to listen for keyboard events. In vanilla JS, the way we would do that is this:
function onKeydown(event) {
console.log(event);
}
document.addEventListener("keydown", onKeydown);
- the
event
object that yourkeydown
listener gets passed is full of useful information, here is a very incomplete typescript type for what data it holds:
type KeyboardEvent {
altKey: boolean; // was the `alt` key held down?
shiftKey: boolean; // was the `shift` key held down?
keyCode: number; // ascii key code, e.g. `72` for "a"
key: string; // "a" if you typed "a"
// ...and lots more info...
}
- by inspecting the
event
object, we can do things based on what key was pressed:
function onKeydown(event) {
if (event.keyCode === "a") {
alert("You typed an 'a'!");
}
}
document.addEventListener("keydown", onKeydown);
- in the React world, adding a listener to the document is definitely a
side-effect, so we would need to set this up using the
useEffect
hook:
const MyComponent: React.FC = () => {
useEffect(() => {
document.addEventListener(`keydown`, (e) => {
if (e.keyCode === `a`) {
alert(`You typed an "a"!`);
}
});
}, []);
return <h1>Hello, world!</h1>;
};
- if you use a setState function INSIDE your effect, that function is
technically a dependency and therefore needs to be listed in the
dependency array to
useEffect
:
const MyComponent: React.FC = () => {
const [typedA, setTypedA] = useState(false);
useEffect(() => {
document.addEventListener(`keydown`, (e) => {
if (e.keyCode === `a`) {
setTypedA(true); // <-- we use it here, so...
}
});
}, [setTypedA]); // đ <-- `setTypedA` is a _dependency_
return <h1>Hello, world!</h1>;
};
- sometimes you need to clean up after a side-effect. Adding a listener to
the document is a good example, because we donât want to keep adding listeners
over and over again â rather, when our effect function is re-run we would
like to clean up the previous effect, if necessary. To that end, the
useEffect
function actually has a Typescript something like this:
type UseEffect = (
effectFn: () => any,
dependencies: Array<any>
) => void | () => any;
- by studying the above type, you can see that
useEffect
must return either nothing (void
), or a function. The function option is a cleanup function. For our example with adding an event listener for keystrokes, we would change our code like this to clean up after ourselves:
const MyComponent: React.FC = () => {
const [typedA, setTypedA] = useState(false);
useEffect(() => {
// here we capture our function in a variable
// so that we can REMOVE it later
const listener = (e) => {
if (e.keyCode === `a`) {
setTypedA(true);
}
};
// add the listener
document.addEventListener(`keydown`, listener);
// return a clean-up function
return () => {
document.removeEventListener(`keydown`, listener);
};
}, [setTypedA]);
return <h1>Hello, world!</h1>;
};
Useful Links:
Homework Plan
đ€ This might end up being a two-week section, Iâll keep you guys posted if we will have class next week, and if not, I will slightly modify the homework, but the core two pieces will be the same.
- 1 day review all flashcards
- 1 day Flashcard App assignment
- 1-2 days Akron Snowmen assignment
- 2 day touch typing practice
- 4 days Execute Program homework
- 1 day watch event bubbling/capturing video
Flashcard App Homework
- slowly and carefully review all of the âNew Stuffâ above ^^^
- merge your MR from last week, switch over to master, pull in your work, and delete the branch from last week
- create a new branch for this weeks work
- create two new virtual cards for your flashcard app in the
css
category. One for declaring a CSS variable, and one for using a CSS variable. - then, add 15 more cards from your physical stack of cards to your app.
- commit your work at this point.
- donât skip step 6 ^
- next, before you work on the new feature, look over your code and try to find some good opportunities to clean things up a bit. Weâve been working on this app for a few weeks already, and weâre only going to keep adding more things. What files are getting really long? Do you see any places where you could extract a component? Maybe reduce some duplication and DRY-up your code? Maybe rename some variables or add some helpful whitespace or comments? Decide on a at least a couple small improvements you could make and do them. These shouldnât change the functionality of the app at all, just improve the code so itâs easier to work with going forward. These types of changes are called refactoring. Refactoring means improving the QUALITY of the CODE without changing what it DOES. When youâve finished, make sure you didnât break anything, and commit your work.
- make sure you actually commited your work after the last step, Iâll want to review just the refactoring commit by itself, separate from the other changes.
- make sure you slowly read the rest of the requirements before starting the next section
- next, a small new feature: CSS variables
- identify 3 good candidates in your CSS for css variables. These could be colors you re-use in multiple files, or special numbers you use for spacing â or really anything you find yourself repeating in your CSS.
- extract 3 (or more) of these candidates out into css variables
- make sure everything still works, and commit your work
- next weâll add this weekâs final new feature: keyboard events:
- add support for at least one set of keyboard events as an alternate method of moving forward, backward, and flipping the card.
- make sure you add all dependencies to your
useEffect
invocations. - make sure you clean up your event listeners.
- remember: baby steps â donât try to do them all at once, or even one whole key listener. Instead do stuff like just add a listener and log out the event object, and build up little by little.
- commit often, so you have lots of restore points if you botch something.
- when youâve finished, commit your work (squash WIP commits if you want, but donât squash the commits from step 6, 8, and 11), and push up a link to your MR and built site, as usual.
- finally, brainstorm at least two ideas for features youâd like to add soon to the Flashcards app. Donât get too wild and crazy (yet). They should be about the size of a homework assignment, and you should be close to being able to do them, maybe with a little help and explanation. Post your ideas in Slack, I think Iâll pick from your ideas in the next few weeks as we keep iterating on this app.
Akron Snowmen Homework
- connect with vscode to the akron snowmen repo you checked out in class on Monday night
- donât run
npm install
just yet⊠- type a command to add a new REMOTE to your git repo. The remote name
must be
upstream
and the remote url isgit@gitlab.howtocomputer.link:htc/akron-snowmen.git
. If you donât remember how to add a remote, try usinggit
s built in help (git help <subcommand>
), or find the spot in the past homework where we went over that. - once youâve successfully added the new remote, type this command (itâs OK if
you donât know exactly what this means, or why weâre doing it, iâll go over it
in the next class):
git pull --rebase upstream master
- now you can type
npm install
to (finish) installing your dependences. (did you know:npm i
is a shortcut fornpm install
đ) - type
<cmd> <shift> f
(usealt
instead ofcmd
if your name is willow) to bring up vscodeâs global search feature. If it appears in your sidebar, drag it into your bottom pane, like I showed you monday night. Use the search feature to find where I added some css variables. (Hint, i used the:root
selector, like a good boy). - briefly peruse the variables I added in that file, you might want to use them later.
- visit the discussion over in our new
#akron-snowmen
channel in Slack. Over there weâre going to try to come up with a list of components that would be good to tackle in week one. - propose one or two new ideas for components
- leave a comment requesting 2 or 3 components that look like youâd like to tackle them â donât start until I actually assign you one or more of these components. Iâm going to weigh the complexity and studentâs comfort level and make the final call (for this week at least) on who is working on what component
- once iâve assigned you one or more components to work on, create a new, well-named branch to start your work
- fire up storybook, and create your component in the
components/
dir. Be sure to start storybook in mobile phone mode because weâre going to be diligent about designing this site mobile first.. - create your component(s) with css using css modules. If your components might
be in multiple different states, make sure they accept props to put them
in those various states, and make sure you have a story for every state.
Note: I donât mean use
useState
state, I just mean something like if youâre making the hamburger, it might need to be open or closed. I do not want you to useuseState
in any of your components this week. If you need to use any of the main colors, be sure to use the css variables I created for you. - when you finish, publish your storybook site using
npm run build-storybook
. After you run this command, you should be able to see it athttp://<yoursubdomain>.howtocomputer.link/storybook-snowmen
. - commit your work, and submit a MR. When creating your MR, take a few minutes to write a carefully crafted paragraph or two describing the work you did, other students will be reading this. If you had to do anything weird, explain the trade-offs you made in the MR comment body. Tell us what we should check out, what you want more input on, etc.
- post in the
#akron-snowmen
channel a link to your built storybook site, and your MR. - for every student who submits a MR, I want you each also to:
- read their MR writeup
- test out their storybook site
- carefully read through the code theyâre submitting, if this gets merged, youâre going to be building on top of this code, so make sure it makes sense, and you think itâs at least mostly well written, as far as you can tell.
- leave at least one truthful positive piece of feedback as a comment on their MR.
- if you see any mistakes, or have any suggestions for making the component or the code better, leave some kindly worded constructive criticism as comments on the MR.
- when other students comment on your MR, address any feedback they give you, if it makes sense and you agree it would make the code better, if you disagree, or donât understand, leave some polite comments in reply to their comments until you reach an understanding and agreement.
- nobody merge any MRs this week â Iâll handle merging things (for now).