Search Results

A search page with loading skeletons, result cards, and pagination.

Preview

Showing 1–4 of 24 results

A versatile button component with multiple variants, sizes, and states.

ng-oat.dev/components/button

Inline badges for status indicators, labels, and counts.

ng-oat.dev/components/badge

Learn how to install and configure ng-oat in your Angular project.

ng-oat.dev/docs/getting-started

Customize colors, spacing, and typography using CSS custom properties.

ng-oat.dev/docs/theming
html
<div class="vstack gap-4 max-w-lg">
  <div class="hstack gap-2">
    <input type="search" placeholder="Search…" class="flex-1" value="Angular components" />
    <button class="btn" (click)="toggleLoading()">Search</button>
  </div>

  @if (loading()) {
    @for (i of [1, 2, 3]; track i) {
      <div class="card">
        <div class="vstack gap-2">
          <ng-oat-skeleton height="1rem" width="60%" />
          <ng-oat-skeleton height="0.75rem" />
          <ng-oat-skeleton height="0.75rem" width="80%" />
        </div>
      </div>
    }
  } @else {
    <small class="text-light">Showing 1–4 of 24 results</small>
    @for (result of results; track result.title) {
      <div class="card">
        <div class="vstack gap-2">
          <div class="hstack gap-2 items-center">
            <a href="#"><strong>{{ result.title }}</strong></a>
            <ng-oat-badge [variant]="result.badgeVariant">{{ result.category }}</ng-oat-badge>
          </div>
          <p class="text-small text-light mb-0">{{ result.description }}</p>
        </div>
      </div>
    }
    <div class="flex justify-center">
      <ng-oat-pagination [totalPages]="6" [currentPage]="1" />
    </div>
  }
</div>

SFC Source

typescript
import { Component, signal } from '@angular/core';
import { NgOatBadge, NgOatPagination, NgOatSkeleton } from '@letsprogram/ng-oat';

@Component({
  selector: 'app-search-results',
  imports: [NgOatBadge, NgOatPagination, NgOatSkeleton],
  template: `
    <div class="vstack gap-4 max-w-lg">
      <div class="hstack gap-2">
        <input type="search" placeholder="Search…" class="flex-1" />
        <button class="btn" (click)="toggleLoading()">Search</button>
      </div>

      @if (loading()) {
        @for (i of [1, 2, 3]; track i) {
          <div class="card">
            <div class="vstack gap-2">
              <ng-oat-skeleton height="1rem" width="60%" />
              <ng-oat-skeleton height="0.75rem" />
              <ng-oat-skeleton height="0.75rem" width="80%" />
            </div>
          </div>
        }
      } @else {
        @for (result of results; track result.title) {
          <div class="card">
            <div class="vstack gap-2">
              <div class="hstack gap-2 items-center">
                <a href="#"><strong>{{ result.title }}</strong></a>
                <ng-oat-badge [variant]="result.badgeVariant">{{ result.category }}</ng-oat-badge>
              </div>
              <p class="text-small text-light mb-0">{{ result.description }}</p>
            </div>
          </div>
        }
        <div class="flex justify-center">
          <ng-oat-pagination [totalPages]="6" [currentPage]="1" />
        </div>
      }
    </div>
  `,
})
export class SearchResultsComponent {
  loading = signal(false);
  results = [
    { title: 'Button Component', category: 'Component', badgeVariant: 'secondary' as const, description: 'A versatile button.' },
    { title: 'Getting Started', category: 'Docs', badgeVariant: 'success' as const, description: 'Install and configure.' },
  ];

  toggleLoading() {
    this.loading.set(true);
    setTimeout(() => this.loading.set(false), 1500);
  }
}