henriquehbr
henriquehbr

Reputation: 1122

Expandable search on app bar with Material Components Web

I'm migrating from Material Design Lite to Material Design Components (Web), i already included both the js and the css packages on my page from unpkg

<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<header id="appBar" class="mdc-top-app-bar mdc-top-app-bar--fixed">
    <div class="mdc-top-app-bar__row">
        <section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
            <div class="mdc-text-field mdc-text-field--fullwidth">
                <input class="mdc-text-field__input" type="text" placeholder="Full-Width Text Field" aria-label="Full-Width Text Field">
            </div>
            <a href="#" class="material-icons mdc-top-app-bar__action-item" aria-label="Bookmark this page" alt="Bookmark this page">close</a>
        </section>
    </div>
</header>

Since then, i was trying to include a search option on the app bar, something that should look like the search bar on material.io, but unfortunately, i couldn't even create something nearly like this

Upvotes: 2

Views: 2329

Answers (1)

Jeevan MB
Jeevan MB

Reputation: 148

Even I was facing this issue. I didn't find any mdc provided component or method as such. So, custom created the effect. Following is a jsfiddle link to the solution.

JSFiddle Link

Reference Links:

  1. MDC TextField With Icon
  2. VueJS Transitions

Migration:

Code is in VueJS. Model and onclick bindings should be easy to migrate to any other framework, but there is an animation for transition may be different in other frameworks.

HTML

<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">

<div id="app">

  <!-- vue based transitions for enter and exit -->
  <transition name="fade">
    <header class="mdc-top-app-bar" v-if="!searchVisible">
      <div class="mdc-top-app-bar__row">

        <section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-start">
          <a href="#" class="material-icons mdc-top-app-bar__navigation-icon">menu</a>
          <span class="mdc-top-app-bar__title">Title</span>
        </section>

         <section class="mdc-top-app-bar__section mdc-top-app-bar__section--align-end" role="toolbar">
          <i class="material-icons mdc-top-app-bar__action-item" aria-label="Download" alt="Download" v-on:click="searchVisible = true">search</i>
        </section>

      </div>
    </header>
  </transition>

  <!-- vue based transitions for enter and exit -->  
  <transition name="fade">

    <!-- to handle enter click on input. This can be handled by handling key event as well. -->
    <form v-on:submit.prevent="postSearch">

      <!-- Even div would work. Made header, as it is replacing the header -->
      <header class="mdc-text-field mdc-text-field--fullwidth mdc-text-field--with-trailing-icon" v-if="searchVisible">
        <input type="text" v-model="searchTerm" id="my-input" class="mdc-text-field__input" placeholder="Search for something" style="padding-left: 16px;">

        <!-- Added a search icon just in case. text-field with trailing icon allows only one, so style  element. (I could be wrong here). Also, applying as class and external css is being overridden by other styles. -->
        <i class="material-icons mdc-text-field__icon" tabindex="0" role="button" v-on:click="postSearch" style="position: absolute; right: 56px;">search</i>

        <i class="material-icons mdc-text-field__icon" tabindex="1" role="button" v-on:click="searchVisible = false">close</i>

        <div class="mdc-line-ripple"></div>
      </header>

    </form>
  </transition>

</div>

VueJS

const topAppBar = mdc.topAppBar.MDCTopAppBar.attachTo(document.querySelector('.mdc-top-app-bar'));
const textField = mdc.textField.MDCTextField.attachTo(document.querySelector('.mdc-text-field'));


new Vue({
  el: "#app",
  data: {
    searchVisible: false,
    searchTerm: ""
  },
  methods: {
    postSearch: function () {
      alert(this.searchTerm);   
    }
  }
});

Upvotes: 2

Related Questions