Vocabulary: [Vue] Footer Component

Created on 26 Sep 2020  路  12Comments  路  Source: creativecommons/vocabulary

We need to implement the Footer component from Vocabulary into its Vue counterpart. The main benefits this component will provide are:

  • Reduce code boilerplate
  • Prevent users from modifying 'fixed' unchanging footer content (CC's logo, address, etc.)

I would like the initial implementation of the component to be _very limited_ in functionality. We can open up customization with additional sub-components and slots in the future, as more diverse use cases become necessary.

Screenshot

Screen Shot 2020-09-25 at 11 51 10 AM

Current HTML version

<footer class="main-footer">
  <div class="container">
    <div class="columns">
      <div class="column is-one-quarter">
        <a href="https://creativecommons.org" aria-label="home" class="main-logo margin-bottom-bigger">
          <span class="has-text-white"><svg
  xmlns="http://www.w3.org/2000/svg"
  preserveAspectRatio="xMidYMid meet"
  viewBox="0 0 304 73">
  <use href="logos/cc/logomark.svg#logomark"></use>
</svg></span>
        </a>
        <div>
          <address class="margin-bottom-normal">Creative Commons<br/>PO Box 1866, Mountain View CA 94042</address>
          <a href="mailto:[email protected]" class="mail">[email protected]</a><br/>
          <a href="tel://+1-415-429-6753" class="phone">+1-415-429-6753</a>
        </div>
        <div class="margin-vertical-large">
          <a href="https://www.instagram.com/creativecommons" aria-label="instagram" class="social has-text-white" target="_blank" rel="noopener">
            <i class="icon margin-right-small is-size-4">instagram</i>
          </a>
          <a href="https://www.twitter.com/creativecommons" aria-label="twitter" class="social has-text-white" target="_blank" rel="noopener">
            <i class="icon margin-right-small is-size-4">twitter</i>
          </a>
          <a href="https://www.facebook.com/creativecommons" aria-label="facebook" class="social has-text-white" target="_blank" rel="noopener">
            <i class="icon margin-right-small is-size-4">facebook</i>
          </a>
          <a href="https://www.linkedin.com/company/creative-commons/" aria-label="linkedin" class="social has-text-white" target="_blank" rel="noopener">
            <i class="icon margin-right-small is-size-4">linkedin</i>
          </a>
        </div>
      </div>
      <div class="column is-three-quarters">
        <div class="columns">
          <div class="column is-full">
            <nav aria-label="footerlinks" class="footer-navigation">
              <ul class="menu">
                <li><a href="#" class="menu-item">Item 1</a></li>
                <li><a href="#" class="menu-item">Item 2</a></li>
                <li><a href="#" class="menu-item">Item 3</a></li>
                <li><a href="#" class="menu-item">Item 4</a></li>
                <li><a href="#" class="menu-item">Item 5</a></li>
                <li><a href="#" class="menu-item">Item 6</a></li>
                <li><a href="#" class="menu-item">Item 7</a></li>
              </ul>
            </nav>
          </div>
        </div>
        <div class="columns">
          <div class="column is-two-thirds">
            <div class="subscription">
              <h5 class="b-header">Subscribe to our newsletter</h5>
              <form class="newsletter">
                <label for="email" class="is-sr-only">Email to subscribe</label>
                <input type="text" id="email" class="input" placeholder="Your email">
                <input type="submit" value="subscribe" class="button small">
              </form>
            </div>
            <div class="attribution margin-top-bigger">
              <p class="caption">
                Except where otherwise
                <a href="https://creativecommons.org/policies#license" target="_blank" rel="noopener">noted</a>,
                content on this site is licensed under a
                <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener">Creative Commons Attribution 4.0 International license</a>.
                <a href="https://creativecommons.org/website-icons" target="_blank" rel="noopener">Icons</a>
                by
                <a href="https://fontawesome.com/" target="_blank" rel="noopener">Font Awesome</a>.
              </p>
              <div class="margin-top-smaller">
                <i class="icon margin-right-small is-size-4">cclogo</i>
                <i class="icon margin-right-small is-size-4">ccby</i>
              </div>
            </div>
          </div>
          <div class="column is-one-third">
            <aside class="donate-section">
              <h5>Our work relies on you!</h5>
              <p>Help us keep the internet free and open.</p>
              <a class="button small donate" href="http://creativecommons.org/donate">
                <i class="icon cc-letterheart-filled margin-right-small is-size-5 padding-top-smaller"></i>
                Donate now
              </a>
            </aside>
          </div>
        </div>
      </div>
    </div>
  </div>
</footer>

Ideal Vue API

The _only_ editable elements of the footer are currently:

  • The blue menu items
  • Custom main content below the menu items (currently only a newsletter form is used)

The <FooterMenuItem> component will use Vue's built in is prop (often seen as an as prop in react) that changes the actual component rendered, allowing for full control of the html element rendered. We need to update vocabulary to make sure none of the styles are dependent on specific html tags, and only on our custom classes.

  <Footer>
    <!-- The default slot contains the main content of the footer, in this case the newsletter form. -->
    <div class="subscription">
      <h5 class="b-header">Subscribe to our newsletter</h5>
      <form class="newsletter">
        <label for="email" class="is-sr-only">Email to subscribe</label>
        <input type="text" id="email" class="input" placeholder="Your email" />
        <input type="submit" value="subscribe" class="button small" />
      </form>
    </div>

    <!-- Instead of named slots we could wrap named slot implementations in custom components, like <FooterMenuItems>, if preferred -->
    <template #menu-items>
      <FooterMenuItem is="a" href="https://wherever.com">Item 1</FooterMenuItem>
      <FooterMenuItem is="router-link" to="/item-two">Item 1</FooterMenuItem>
    </template>
  </Footer>
help wanted addition ready for work javascripstorybook javascripvue code interface medium dx

Most helpful comment

@dhruvkb oops! I want to use Vue's built-in is, I must have had Buefy's docs open when i wrote it. Edited.

All 12 comments

@dhruvkb please review the proposed component api here when you get a chance; thanks!

@zackkrida the proposal looks great, just one question though: why not name the prop is?

@dhruvkb oops! I want to use Vue's built-in is, I must have had Buefy's docs open when i wrote it. Edited.

@dhruvkb @zackkrida I would like to take this up.

Go for it @megha070 馃槃

@nimishbongale you can track the development of the Footer component here.

@zackkrida @dhruvkb

I think a similar issue will need to be raised for 'Header' as well?

@nimishbongale https://github.com/creativecommons/vocabulary/issues/642 (I'll clean it up a little this week)

I'd like to take this if @megha070 is no longer working on it

@akmadian I'd say go for it, with the suggestion to get a draft PR up as early in the process as you're comfortable. If at some point we realize we have two active PRs we can get everyone working together from there.

RE: the possibility of wrapping named slots in a custom component, I'm not sure I see the benefit. It would create a simpler implementation for us and users to just use a slot or a named slot since it eliminates the dependency on the FooterMenuItem component, simplifies the syntax of implementing the component, and will simplify the documentation of the component.

Is there some reason for this that I'm missing?

@akmadian I think we all agree the slot is the best path forward.

Only reason for a custom component would be code style, or other use cases not needed in this component.

Was this page helpful?
0 / 5 - 0 ratings