Components - Search module

Search Bar with minimalistic look

This module is a stylised search bar with a modern look. Provides an ng-model parameter to be able to define on what context the search will take place. When hovering over the search bar, the hover color will be the var(--links) color defined in the portal theme.

<ods-dataset-context context="worldheritagelistpublicus"
                     worldheritagelistpublicus-dataset="world-heritage-list"
                     worldheritagelistpublicus-domain="public-us"
                     worldheritagelistpublicus-parameters="{'disjunctive.states':true,'sort':'date_inscribed'}">
    <div class="search-module">
        <i class="fa fa-search search-module-icon" aria-hidden="true"></i>
        <input placeholder="Search in dataset"
               ng-model="worldheritagelistpublicus.parameters['q']"
               ng-model-options="{ updateOn: 'keyup', debounce: { 'default': 300, 'blur': 0 }}"
               class="search-module-input"
               type="text"/>
        <button class="search-module-clear"
                ng-if="worldheritagelistpublicus.parameters['q']"
                ng-click="worldheritagelistpublicus.parameters['q'] = undefined">
            <i class="fa fa-times-circle" aria-hidden="true"></i>
        </button>
    </div>
    <ods-table context="worldheritagelistpublicus" sort="date_inscribed"></ods-table>
</ods-dataset-context>
/* Search Module
   ========================================================================== */
.search-module {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid #dee5ef;
  margin-bottom: 20px;
  transition: all .2s;
}
.search-module:hover,
.search-module:focus-within {
  border-bottom-color: var(--links);
}
.search-module-icon {
  color: #898d92;
  margin-right: 8px;
  align-self: center;
}
.search-module-input {
  background-color: transparent;
  width: 100%;
  outline: none;
  border: none;
  padding: 12px 0;
  transition: all .2s;
  color: var(--text);
}
.search-module-input::placeholder {
  transition: all .2s;
}
.search-module-clear {
  color: #898d92;
  font-size: 1rem;
  background: transparent;
  border: none;
  margin: 0;
  outline: none;
  padding: 0 0 0 12px;
  transition: all .2s;
}
.search-module-clear:hover {
  opacity: .65;
}
.search-module:hover .search-module-icon,
.search-module:focus-within .search-module-icon,
.search-module:hover .search-module-input::placeholder,
.search-module:focus-within .search-module-input::placeholder {
  color: var(--links)
}

Search Bar with results

Based on the search module above, we can add ods-results to list search matches

<ods-dataset-context context="ctx"
                     ctx-dataset="communes-et-arrondissements-municipaux-france"
                     ctx-domain="userclub">
    <div class="search-module">
        <i class="fa fa-search search-module-icon" aria-hidden="true"></i>
        <input placeholder="Search in dataset"
               ng-model="ctx.parameters['q']"
               ng-model-options="{ updateOn: 'keyup', debounce: { 'default': 300, 'blur': 0 }}"
               class="search-module-input"
               type="text"/>
        <button class="search-module-clear"
                ng-if="ctx.parameters['q']"
                ng-click="ctx.parameters['q'] = undefined">
            <i class="fa fa-times-circle" aria-hidden="true"></i>
        </button>
    </div>
    <ul class="display-tags"
        ods-results="results"
        ods-results-context="ctx"
        ods-results-max="11">
        <li ng-repeat="(i,item) in results"
            ng-if="ctx.parameters['q'] && i <= 9">
            <a ng-href="{{ 'https://www.google.fr/maps/search/' + item.fields.com_name }}" target="_blank">
                {{item.fields.com_name }} ({{item.fields.dep_name }}) <i class="fa fa-map-marker" aria-hidden="true"></i>
            </a>
        </li>
        <li class="more-than-ten"
            ng-if="ctx.parameters['q'] && results.length > 10">
            More than 10 results. Continue typing to narrow your search...
        </li>
    </ul>
</ods-dataset-context>
/* Search Module
========================================================================== */
.search-module {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid #dee5ef;
  margin-bottom: 20px;
  transition: all .2s;
}
.search-module:hover,
.search-module:focus-within {
  border-bottom-color: var(--links);
}
.search-module-icon {
  color: #898d92;
  margin-right: 8px;
  align-self: center;
}
.search-module-input {
  background-color: transparent;
  width: 100%;
  outline: none;
  border: none;
  padding: 12px 0;
  transition: all .2s;
  color: var(--text);
}
.search-module-input::placeholder {
  transition: all .2s;
}
.search-module-clear {
  color: #898d92;
  font-size: 1rem;
  background: transparent;
  border: none;
  margin: 0;
  outline: none;
  padding: 0 0 0 12px;
  transition: all .2s;
}
.search-module-clear:hover {
  opacity: .65;
}
.search-module:hover .search-module-icon,
.search-module:focus-within .search-module-icon,
.search-module:hover .search-module-input::placeholder,
.search-module:focus-within .search-module-input::placeholder {
  color: var(--links)
}



/* Display results */

.display-tags {
  display: flex;
  flex-wrap: wrap;
  margin: 20px 10px;
  padding: 0;
}
.display-tags li {
  list-style: none;
}
.display-tags a {
  align-items: center;
  background-color: #f5f5f5;
  border-radius: 4px;
  color: #4a4a4a;
  display: inline-flex;
  font-size: 0.85rem;
  justify-content: center;
  line-height: 1.5;
  padding: 0.25em .75em;
  white-space: nowrap;
  margin: 0.2rem;
  text-decoration: none;
}
.display-tags a i {
    margin-left: 6px;
}
.display-tags a:focus, .display-tags a:hover {
  border-color: #4a4a4a;
  background-color: #d0d0d0;
}

.more-than-ten {
  display: flex;
  align-items: center;
  color: #4a4a4a;
  padding: 2px 5px;
}

Search Bar with results + accessibility

The same search bar, with additional aria-* and role attributes and text content for screen readers.

<ods-dataset-context context="ctx"
                     ctx-dataset="communes-et-arrondissements-municipaux-france"
                     ctx-domain="userclub">
    <div class="search-module">
        <div class="search-bar">
            <i class="fa fa-search search-bar-icon" aria-hidden="true"></i>
            <label for="search-as-you-type" class="sr-only">Search for a city</label>
            <input id="search-as-you-type"
                   name="search-as-you-type"
                   autocomplete="off"
                   aria-label="search-as-you-type: type some characters to make a search"
                   aria-expanded="{{ ctx.parameters['q'] != undefined }}"
                   aria-controls="search-results"
                   placeholder="Search in dataset"
                   ng-model="ctx.parameters['q']"
                   ng-model-options="{ updateOn: 'keyup', debounce: { 'default': 300, 'blur': 0 }}"
                   class="search-bar-input"
                   type="text"/>
            <button aria-label="Clear search"
                    class="search-bar-clear"
                    ng-if="ctx.parameters['q']"
                    ng-click="ctx.parameters['q'] = undefined">
                <i class="fa fa-times-circle" aria-hidden="true"></i>
                <span class="sr-only">Clear search</span>
            </button>
        </div>
        <div class="search-results">
            <span class="sr-only">
                Search results will be displayed bellow, as a list of external links
            </span>
            <ul class="display-tags"
                ods-results="results"
                ods-results-context="ctx"
                ods-results-max="11"

                aria-label="search-as-you-type results displayed here when a search is made"
                aria-live="polite"
                aria-atomic="true"
                aria-labelledby="search-as-you-type"
                role="group"

                id="search-results">
                <li ng-repeat="(i,item) in results"
                    ng-if="ctx.parameters['q'] && i <= 9"
                    role="listitem">
                    <a ng-href="{{ 'https://www.google.fr/maps/search/' + item.fields.com_name }}" target="_blank">
                        {{item.fields.com_name }} ({{item.fields.dep_name }}) <i class="fa fa-map-marker" aria-hidden="true"></i>
                        <span class="sr-only">Open selected city in another tab</span>
                    </a>
                </li>
                <li class="more-than-ten"
                    role="listitem"
                    ng-if="ctx.parameters['q'] && results.length > 10">
                    More than 10 results. Continue typing to narrow your search...
                </li>
            </ul>
        </div>
    </div>
</ods-dataset-context>
/* Search Module
========================================================================== */
.search-bar {
  display: flex;
  align-items: stretch;
  border-bottom: 1px solid #dee5ef;
  margin-bottom: 20px;
  transition: all .2s;
}
.search-bar:hover,
.search-bar:focus-within {
  border-bottom-color: var(--links);
}
.search-bar-icon {
  color: #898d92;
  margin-right: 8px;
  align-self: center;
}
.search-bar-input {
  background-color: transparent;
  width: 100%;
  outline: none;
  border: none;
  padding: 12px 0;
  transition: all .2s;
  color: var(--text);
}
.search-bar-input::placeholder {
  transition: all .2s;
}
.search-bar-clear {
  color: #898d92;
  font-size: 1rem;
  background: transparent;
  border: none;
  margin: 0;
  outline: none;
  padding: 0 0 0 12px;
  transition: all .2s;
}
.search-bar-clear:hover {
  opacity: .65;
}
.search-bar:hover .search-bar-icon,
.search-bar:focus-within .search-bar-icon,
.search-bar:hover .search-bar-input::placeholder,
.search-bar:focus-within .search-bar-input::placeholder {
  color: var(--links)
}



/* Display results */

.display-tags {
  display: flex;
  flex-wrap: wrap;
  margin: 20px 10px;
  padding: 0;
}
.display-tags li {
  list-style: none;
}
.display-tags a {
  align-items: center;
  background-color: #f5f5f5;
  border-radius: 4px;
  color: #4a4a4a;
  display: inline-flex;
  font-size: 0.85rem;
  justify-content: center;
  line-height: 1.5;
  padding: 0.25em .75em;
  white-space: nowrap;
  margin: 0.2rem;
  text-decoration: none;
}
.display-tags a i {
    margin-left: 6px;
}
.display-tags a:focus, .display-tags a:hover {
  border-color: #4a4a4a;
  background-color: #d0d0d0;
}

.more-than-ten {
  display: flex;
  align-items: center;
  color: #4a4a4a;
  padding: 2px 5px;
}