A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://medium.com/@jdan/rendering-khan-academys-learn-menu-wherever-i-please-4b58d4a9432d below:

Rendering Khan Academy’s Learn Menu Wherever I Please | by Jordan Scales

Rendering Khan Academy’s Learn Menu Wherever I Please 5 min read

·

Sep 14, 2016

The combination of React and CSS-in-JS just saved me about two days of work.

Over the next few months we’ll be running some A/B testing on Khan Academy’s logged out homepage. One such experiment involves placing the subjects menu beneath the main site banner:

Press enter or click to view image in full size

Here’s a tale of how I implemented this change to one of our most important pages quickly and confidently using some modern frontend tooling.

What we’re working with

Currently, the learn menu sits in the site-wide navigation bar. You have to click “Subjects” at the top left to open it.

So all we need to do is take that thing, and put it in the markup of the logged-out homepage. Easy stuff, right? In 2015’s Khan Academy tech stack this entails:

Two days later I now have the learn menu rendering in two different places, so I can sit back and relish in my success before realizing I broke the text alignment in the site-wide footer. (How was I supposed to know, who scrolls down that far anyway?)

But, this is 2016, and in 2016 we do things a little differently.

The LearnMenu Component

In 2016 we ditched the old handlebars template and created a <LearnMenu> component. It’s quite nice — it accepts a prop specifying all the sections and links within those sections. It then renders a few other shared components like <Link> and <DropdownButton> to keep the learn menu aligned with our style guidelines.

So I sat down and extracted just the stuff I needed (again, just the 5 columns and none of the dropdown business) into a separate component.

There’s nothing too exciting about this: your framework has components too. Also we can refactor with handlebars just fine — the learn menu is pretty static and doesn’t (yet) have any fancy callbacks or lifecycle methods that made this refactoring especially interesting or delightful.

The LearnMenu component does have one particularly useful thing within it, though:

return <ul
className={css(
styles.domains,
this.props.hasFiveColumns && styles.domainsFiveColumns
)}
>
{this.props.domains.map(this.renderDomain)}
</ul>;

There’s a fancy “css()” function, and two references to “styles.” If we scroll down we can see what those are about. (Bear with me, here)

domains: {
...sharedStyles.defaultAlignment,
paddingBottom: sectionPadding - gapBetweenStackedDomains,
columnCount: 4,
},
domainsFiveColumns: {
[mediaQueries.xl]: {
columnCount: 5,
},
},

That stuff is an ordinary JavaScript object, where the keys resemble CSS properties (except camelCased, so “padding-bottom” becomes “paddingBottom”). This is a library we wrote at Khan Academy called Aphrodite.

When I call the “css()” function on something like “domains,” I’ll get back a whacky class name like “domains_o3z00m-o_O-domainsFiveColumns_1xgyot8” that I can set as the “className” of the React element. This seems unwieldy (CSS in JavaScript oh no why!?), but has a few immediate benefits:

It’s unique to this component. In 2015 we might have written a “.domains {}” CSS rule. Someone else may come along and use “.domains {}” in a separate feature. Someone else may come along and change “.domains {}” for that second use-case, unaware that the original usage of “.domains {}” is now broken. We might fix this by scoping “.domains {}” to something like “#global-nav .domains {},” and then 2016 Jordan comes along and gets really sad and writes a blog post.

It travels with the component. When I render <LearnMenu> on a page, I don’t need to worry about also including “learn-menu.css” (or whatever package its contained in). I get precisely the styles I need, exactly where I need them. Aphrodite works perfectly with server-side rendering, so our CSS loads on the client just as quickly as it used to.

It still uses shared properties. The “CSS” above contains a few constants (sharedStyles.defaultAlignment, sectionPadding, and mediaQueries.xl) which are shared both internally and externally throughout our codebase. At Khan Academy we maintain a style guide full of media queries, colors, and alignment properties that we can use from our components. This is identical to the “variables.less” you have in your codebase, except instead of sharing it with some specific syntax like “@import” we use JavaScript’s “require” — it works just fine!

One Happy Developer

Using this tooling, we can now confidently render the learn menu on any page we want. If in the future we want to move the learn menu down, or put it under a video, we can do so quickly and with confidence — that’s quite the feat!

We can even render the learn menu on pages like Khan Academy’s “react-sandbox” which allows us to see what a component looks like with various combinations of props.

Press enter or click to view image in full size

Still, at this point I’m not actually doing anything that I couldn’t do by hand. Techniques like OOCSS and BEM were built to help developers write perfect CSS to accomplish many of the items I listed above.

The difference is, I’m letting JavaScript figure out when and where I should load my stylesheet.

I’m letting JavaScript handle all my constants and shared mixins.

I’m letting JavaScript write the perfect CSS for me.

“Separation of concerns” you may chant. Well, I’ve separated my concerns for 10 years, and now I’m too scared to touch my CSS.

We’re still figuring out cool patterns with CSS-in-JS, and the landscape is rapidly (and to many, frustratingly) changing, but in 2016 we’re finally capable of removing some of the most annoying parts of frontend web development — and that’s something to embrace.

For more information on Aphrodite, check out the GitHub page and Kent C. Dodds’s awesome video series.

Be sure to follow me on twitter for rants like these in fewer characters.

We do lots of open source at Khan Academy, so come join us if that sounds awesome to you. 👋


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4