Beyond the WAT
Why Component Design Still Matters
Becca Nelson • @beccaliz • becca.is
beccaliz
👩💻 The Mom Project
🏡 Chicago, IL USA
About Me
💜
beccaliz
component design
a11y
beccaliz
beccaliz
As I started working on the front-end more and more, there was this subtle attitude shift.
beccaliz
Have you ever tried using the builder pattern?
beccaliz
Great job working on the frontend! I think you should develop your skills more so you can be a strong contributor on the backend too!
beccaliz
beccaliz
beccaliz
Backend development is “hard and scary” while frontend development is just the pretty interface on top.
beccaliz
JavaScript has been a pretty historically unruly language.
beccaliz
> [] + []
""
> [] + {}
"[object Object]"
> {} + []
0
beccaliz
beccaliz
beccaliz
It’s no longer just a necessary evil for building pretty UIs that we can pawn off on our junior engineers.
beccaliz
Component Design
What it looks like
Why it matters
beccaliz
Framework-specific design patterns
Overarching guiding principles
Framework-specific design patterns
beccaliz
As JavaScript engineers in 2019, what does it mean to design good components?
beccaliz
1. Accessibility
2. Scalability
3. Single Reponsibility
4. Testability
beccaliz
Accessibility
beccaliz
⚠️ Disclaimer
beccaliz
Semantic HTML
-
Using the most appropriate HTML tags for your content
-
Using HTML in a way that a user could navigate and understand the hierarchy of your site by using HTML alone.
beccaliz
Heading tags
Should be used in order
Should not be used to re-size content
beccaliz
<h1>Most important!</h1>
<h2>Second most important!</h2>
<h3>Third most important!</h3>
beccaliz
Most important!
Second most important!
Third most important!
beccaliz
<div className="content">
<button onClick={() => doSomething()}>
Click me!
</button>
<a href="/my/route">Go home</a>
</div>
beccaliz
<div onClick={() => doSomething()}>
// Content
</div>
❌
beccaliz
<i className="icon-email" title="Email me!"/>
beccaliz
-
Keyboard navigation
-
Color contrast
-
Font size / scaling
beccaliz
a11y Linter
Auditing Tools
http://a11yproject.com/resources
beccaliz
Scalability
beccaliz
beccaliz
beccaliz
No matter whether you are using dynamic or static types, no matter whether you are writing for the web or for the server...
beccaliz
Scalability is hard.
beccaliz
Because of people.
beccaliz
Bigger products = bigger teams.
beccaliz
With bigger teams, the more we need to be explicit about the choices we are making and why we are making them.
beccaliz
Single Responsibility
beccaliz
What does it mean for a component to be single responsibility?
beccaliz
It does only one thing.
beccaliz
<div className="card">
<div className="card__header">
<img className="card__image" src="/image"/>
Some header content
</div>
<div className="card__body">
Some body content
</div>
<button
className="card__toggle"
onClick={() => toggle()}
/>
</Card>
beccaliz
Single responsibility = testability & reusability
beccaliz
We can use naming to make it explicit that certain components belong together.
beccaliz
<Card>
<CardHeader>
<CardImage src="/image"/>
Some header content
</CardHeader>
<CardBody>
Some body content
</CardBody>
</Card>
beccaliz
<Card>
<Card.Header>
<Card.Image src="/image"/>
Some header content
</Card.Header>
<Card.Body>
Some body content
</Card.Body>
</Card>
beccaliz
Testability
class UserProfile extends React.Component {
state = {
profile: undefined
};
componentDidMount() {
fetch("/my/profile").then(response => {
this.setState({
profile: response.json()
});
});
}
render() {
if (this.state.profile) {
return (
<div className="user-profile">
<div>Name: {this.state.profile.name}</div>
<div>Email: {this.state.profile.email}</div>
</div>
);
}
}
}
global.fetch.mockImplementation(() => {
return new Promise(resolve => {
resolve({
ok: true,
json: () => {
return {
name: "Jane Smith",
email: "jane@example.com"
}
}
});
});
});
class UserProfile extends React.Component {
state = {
profile: undefined,
completed: false,
};
componentDidMount() {
...
}
render() {
if (!this.state.completed) {
return (
<a href="/profile/edit">Complete your profile!</a>
)
}
else if (this.state.profile) {
return (
<div className="user-profile">
<div>Name: {this.state.profile.name}</div>
<div>Email: {this.state.profile.email}</div>
</div>
);
}
}
}
class UserProfile extends React.Component {
state = {
profile: undefined,
completed: false,
};
componentDidMount() {
...
}
render() {
if (!this.state.completed) {
return (
<a href="/profile/edit">Complete your profile!</a>
)
}
else if (this.state.profile) {
return (
<div className="user-profile">
<div>Name: {this.state.profile.name}</div>
<div>Email: {this.state.profile.email}</div>
</div>
);
}
}
}
beccaliz
beccaliz
Displaying Information
Interacting with outside world
beccaliz
Another note on testing...
beccaliz
Testing is a core tenet of good component design.
beccaliz
Our tests can be living documentation of our components and how they are intended to work.
beccaliz
Why does this matter?
beccaliz
beccaliz
🤩 🥳 👏 💯
beccaliz
beccaliz
Put yourselves in the shoes of a user, or a new teammate, or even yourself a year from now.
beccaliz
What are the things that would help you to understand what is going on?
beccaliz
What are the things that would help you to feel empowered to contribute without re-inventing the wheel or breaking existing functionality?
beccaliz
beccaliz
Thank you!!
Beyond the WAT: Why Component Design Still Matters
By Becca Nelson
Beyond the WAT: Why Component Design Still Matters
n the tech community, sometimes JavaScript gets a bad rap. From its type inconsistencies to its 90’s-era syntax to its status as a “less important” programming language, JavaScript is sometimes seen as a necessary evil that should be avoided whenever possible. But as components become more complicated and accessible user interfaces become a bare minimum requirement, the work we do with this language is more important than ever. Let’s talk about good component design—what it looks like and why it matters.
- 1,317