BrowseSearch

Navigation

Glass Search

A glass search button that opens into a field, as on iOS: the field grows out of the button toward the start and its magnifying glass turns into a close mark. Use it in a header, a toolbar, a tab bar or anywhere else.

Preview

Library

Picks for you, fresh every morning.

Installation

Install the package once, then import the parts you use into a standalone component.

Install

npm install ngx-vitreo @angular/cdk @floating-ui/dom
Import

import { GlassSearch, GlassTabBar } from 'ngx-vitreo';

@Component({
  imports: [GlassSearch, GlassTabBar],
  // ...
})

Usage

Usage

<!-- In a header: it opens over the links. -->
<header glassHeader class="docs-search-header" navigationLabel="Example navigation" position="static">
  <a glassHeaderBrand href="#music" (click)="$event.preventDefault()">Vitreo Music</a>
  <ng-template glassHeaderLinks>
    <a href="#listen" (click)="$event.preventDefault()">Listen</a>
    <a href="#browse" (click)="$event.preventDefault()">Browse</a>
  </ng-template>
  <glass-search glassHeaderActions placeholder="Search the catalogue" />
</header>

<!-- Anywhere else: it opens over what lies before it in its container. -->
<div class="docs-search-toolbar">
  <h3 class="docs-search-title">Library</h3>
  <glass-search placeholder="Search your library" />
</div>

<!-- In a tab bar: the tabs fold away for it. -->
<glass-tabs class="docs-search-demo" [(value)]="tab">
  <div class="docs-search-screen">
    @if (searching()) {
      <glass-panel class="docs-search-results" variant="card">
        <p class="docs-search-heading">{{ query() ? 'Top results' : 'Recently played' }}</p>
        @for (song of results(); track song) {
          <p class="docs-search-row">{{ song }}</p>
        } @empty {
          <p class="docs-search-row docs-search-empty">No results for “{{ query() }}”</p>
        }
      </glass-panel>
    }
    <div [hidden]="searching()">
      <glass-tabs-content value="home">Picks for you, fresh every morning.</glass-tabs-content>
      <glass-tabs-content value="browse">New releases and editors' playlists.</glass-tabs-content>
      <glass-tabs-content value="radio">Live stations from around the world.</glass-tabs-content>
      <glass-tabs-content value="library">Everything you've saved.</glass-tabs-content>
    </div>
  </div>
  <glass-tab-bar>
    <glass-tabs-list aria-label="Music">
      <button glassTabsTrigger value="home">
        <svg aria-hidden="true" viewBox="0 0 24 24"><path d="M4.5 10.2 12 4l7.5 6.2V19a1 1 0 0 1-1 1H15v-5.5H9V20H5.5a1 1 0 0 1-1-1z" /></svg>
        Home
      </button>
      <button glassTabsTrigger value="browse">
        <svg aria-hidden="true" viewBox="0 0 24 24"><rect x="4" y="4" width="6.6" height="6.6" rx="1.8" /><rect x="13.4" y="4" width="6.6" height="6.6" rx="1.8" /><rect x="4" y="13.4" width="6.6" height="6.6" rx="1.8" /><rect x="13.4" y="13.4" width="6.6" height="6.6" rx="1.8" /></svg>
        Browse
      </button>
      <button glassTabsTrigger value="radio">
        <svg aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="1.9" /><path d="M8.3 15.7a5.2 5.2 0 0 1 0-7.4m7.4 0a5.2 5.2 0 0 1 0 7.4M5.6 18.4a9 9 0 0 1 0-12.8m12.8 0a9 9 0 0 1 0 12.8" /></svg>
        Radio
      </button>
      <button glassTabsTrigger value="library">
        <svg aria-hidden="true" viewBox="0 0 24 24"><path d="M5.5 4.5v15M10 4.5v15M14.2 5.2l4.6 14" /></svg>
        Library
      </button>
    </glass-tabs-list>
    <glass-search placeholder="Artists, songs and more" [(open)]="searching" [(value)]="query" />
  </glass-tab-bar>
</glass-tabs>

API reference

GlassSearch

glass-search

InputTypeDefaultDescription
[(open)]booleanfalseWhether the field is out. The button opens and closes it.
[(value)]string''The search text. Also works with ngModel and formControl.
placeholderstring'Search'Shown in the empty field, and the field's accessible name unless fieldLabel is set.
fieldLabelstringNoneThe field's accessible name, when the placeholder alone doesn't say enough.
buttonLabel / closeLabel / clearLabelstring'Search' / 'Close search' / 'Clear search'Accessible names of the button, closed and open, and of the clear button.
clearOnClosebooleantrueClears the text when the search closes, as cancelling a search does on iOS.
disabledbooleanfalseStops the search opening.
expand'cover' | 'inline''cover'Cover spreads the open field back over what lies before the button in its area, which steps aside, so the layout never moves. Inline widens the search in place, for a container that makes room. A glass-header or glass-tab-bar picks for you.
areaHTMLElement the parent The element an open field covers. In a glass-header it is the bar after the brand.
buttonVariant'primary' | 'prominent' | 'ghost' | 'soft''primary'The button's look. In a glass-header it is ghost, like the header's other actions.
(submitted)stringNoneEmits the text when Enter is pressed in the field. Escape closes the search.

GlassTabBar

glass-tab-bar

InputTypeDefaultDescription
contentglass-tabs-list + glass-searchNoneFolds the tabs into a circle showing the selected tab's icon while search is open; a press on it closes search. Give each trigger an icon and a label.