Beyond the WAT

Why Component Design Still Matters

Becca Nelson • @beccaliz • becca.is

👩‍💻 The Mom Project

🏡 Chicago, IL USA

About Me

💜

component design

a11y

As I started working on the front-end more and more, there was this subtle attitude shift.

Have you ever tried using the builder pattern?
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!

Backend development is “hard and scary” while frontend development is just the pretty interface on top.

JavaScript has been a pretty historically unruly language.

> [] + []
""

> [] + {}
"[object Object]"

> {} + []
0

It’s no longer just a necessary evil for building pretty UIs that we can pawn off on our junior engineers. 

Component Design

What it looks like

Why it matters

Framework-specific design patterns

Overarching guiding principles

Framework-specific design patterns

As JavaScript engineers in 2019, what does it mean to design good components?

1. Accessibility

2. Scalability

3. Single Reponsibility

4. Testability

Accessibility

⚠️ Disclaimer

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.

Heading tags

Should be used in order

Should not be used to re-size content

<h1>Most important!</h1>
<h2>Second most important!</h2>
<h3>Third most important!</h3>

Most important!

Second most important!

Third most important!

<div className="content">
    <button onClick={() => doSomething()}>
        Click me!
    </button>
    <a href="/my/route">Go home</a>
</div>
<div onClick={() => doSomething()}>
   // Content
</div>

<i className="icon-email" title="Email me!"/>
  • Keyboard navigation

  • Color contrast

  • Font size / scaling

a11y Linter

Auditing Tools

http://a11yproject.com/resources

Scalability

No matter whether you are using dynamic or static types, no matter whether you are writing for the web or for the server...

Scalability is hard.

Because of people.

Bigger products = bigger teams.

With bigger teams, the more we need to be explicit about the choices we are making and why we are making them.

Single Responsibility

What does it mean for a component to be single responsibility?

It does only one thing.

<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>

Single responsibility = testability & reusability

We can use naming to make it explicit that certain components belong together.

<Card>
  <CardHeader>
    <CardImage src="/image"/>
    Some header content    
  </CardHeader>
  <CardBody>
    Some body content
  </CardBody>
</Card>
<Card>
  <Card.Header>
    <Card.Image src="/image"/>
    Some header content    
  </Card.Header>
  <Card.Body>
    Some body content
  </Card.Body>
</Card>

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>
      );
    }
  }
}

Displaying Information

Interacting with outside world

Another note on testing...

Testing is a core tenet of good component design.

Our tests can be living documentation of our components and how they are intended to work.​

Why does this matter?

🤩 🥳 👏 💯

Put yourselves in the shoes of a user, or a new teammate, or even yourself a year from now. ​

What are the things that would help you to understand what is going on? ​

What are the things that would help you to feel empowered to contribute without re-inventing the wheel or breaking existing functionality?

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,308