Angular Search Button Component

Search Button

Release candidate (RC)

This component is in the Release Candidate phase and its API is considered stable. Minor adjustments may still occur before the final release.

Angular search button component for keyboard-aware search entry points, command palettes, modals, and offcanvas panels.

Available in Other JavaScript Frameworks

CoreUI Angular Search Button Component is also available for Bootstrap, React, and Vue. Explore framework-specific implementations below:

Added in v5.7.19

Overview

The CoreUI Angular Search Button component is a trigger element designed for search entry points and command-style actions. It behaves like a regular button on click, but it can also react to a configurable keyboard shortcut such as meta+/ or ctrl+/.

  • Use it as a standalone trigger for a custom search UI.
  • Pair it with a signal to open a modal, offcanvas, or command palette.
  • Shortcut keys are rendered automatically.
  • Displayed shortcut keys react to keyboard interaction and receive an .active state while pressed.

Examples

Basic example

Use <c-search-button> as the entry point for a controlled search interface. Use the (trigger) output as the main activation callback for both direct interaction and keyboard shortcuts.

import { Component, signal } from '@angular/core';
import {
  BadgeComponent,
  FormControlDirective,
  ListGroupDirective,
  ListGroupItemDirective,
  ModalBodyComponent,
  ModalComponent,
  ModalHeaderComponent,
  ModalTitleDirective,
  SearchButtonComponent
} from '@coreui/angular';

@Component({
  selector: 'docs-search-button-basic',
  templateUrl: './search-button-basic.component.html',
  imports: [
    BadgeComponent,
    FormControlDirective,
    ListGroupDirective,
    ListGroupItemDirective,
    ModalBodyComponent,
    ModalComponent,
    ModalHeaderComponent,
    ModalTitleDirective,
    SearchButtonComponent
  ]
})
export class SearchButtonBasicComponent {
  readonly visible = signal(false);

  onTrigger(): void {
    this.visible.set(true);
  }
}
<c-search-button
  (trigger)="onTrigger()"
  aria-label="Open search dialog"
  aria-controls="search-button-modal"
  shortcut="meta+/,ctrl+/"
/>

<c-modal id="search-button-modal" [(visible)]="visible" aria-labelledby="search-button-modal-title">
  <c-modal-header>
    <h5 cModalTitle id="search-button-modal-title" class="w-100">
      <input cFormControl type="search" placeholder="Search" aria-label="Search" />
    </h5>
  </c-modal-header>
  <c-modal-body>
    <p class="text-body-secondary small mb-2">Recent searches</p>
    <ul cListGroup flush>
      <li cListGroupItem class="d-flex justify-content-between align-items-center">
        CoreUI components overview
        <c-badge color="secondary" shape="rounded-pill">Open</c-badge>
      </li>
      <li cListGroupItem class="d-flex justify-content-between align-items-center">
        Modal dialog examples
        <c-badge color="secondary" shape="rounded-pill">Open</c-badge>
      </li>
      <li cListGroupItem class="d-flex justify-content-between align-items-center">
        Sidebar navigation customization
        <c-badge color="secondary" shape="rounded-pill">Open</c-badge>
      </li>
    </ul>
  </c-modal-body>
</c-modal>

Custom icon

Override the default icon by projecting an <ng-template cTemplateId="icon"> — the rest of the button (placeholder and shortcut keys) stays untouched. Apply the search-button-icon class to the projected element so it picks up the same --cui-search-button-icon-size sizing as the default icon.

import { Component } from '@angular/core';
import { cilCompass } from '@coreui/icons';
import { IconDirective } from '@coreui/icons-angular';
import { SearchButtonComponent, TemplateIdDirective } from '@coreui/angular';

@Component({
  selector: 'docs-search-button-custom-icon',
  templateUrl: './search-button-custom-icon.component.html',
  imports: [IconDirective, SearchButtonComponent, TemplateIdDirective],
})
export class SearchButtonCustomIconComponent {
  icons = { cilCompass };
}
<c-search-button aria-label="Search" shortcut="meta+.,ctrl+.">
  <ng-template cTemplateId="icon">
    <svg [cIcon]="icons.cilCompass" aria-hidden="true" class="search-button-icon"></svg>
  </ng-template>
</c-search-button>

Custom shortcut

Configure the shortcut with the shortcut input. On macOS, the component prefers the meta variant for the visible label. On Windows and Linux, it prefers the ctrl variant.

Shortcuts such as meta+f, ctrl+f, meta+s, or ctrl+s can override native browser or system shortcuts. Prefer safer combinations such as meta+/ and ctrl+/ unless replacing the default behavior is intentional.

import { Component, signal } from '@angular/core';
import { AlertComponent, SearchButtonComponent } from '@coreui/angular';

@Component({
  selector: 'docs-search-button-custom-shortcut',
  templateUrl: './search-button-custom-shortcut.component.html',
  imports: [AlertComponent, SearchButtonComponent]
})
export class SearchButtonCustomShortcutComponent {
  readonly count = signal(0);
  readonly disabled = signal(false);

  onTrigger(): void {
    this.count.update((value) => value + 1);
    if (this.count() > 9) {
      this.disabled.set(true);
    }
  }
}
<c-search-button
  (trigger)="onTrigger()"
  [disabled]="disabled()"
  aria-label="Open command palette"
  placeholder="Command palette"
  shortcut="meta+i,ctrl+i"
/>
<c-alert class="mt-3 mb-0" color="info">
  Triggered {{ count() }} {{ count() === 1 ? 'time' : 'times' }} with click or shortcut. {{ disabled() ? 'Disabled!' : '' }}
</c-alert>

Launch an offcanvas

The component works naturally with a controlled visible signal and also supports a dedicated (trigger) output. This demo uses meta+shift+o / ctrl+shift+o to avoid colliding with other live examples on the page.

import { Component, signal } from '@angular/core';
import {
  ButtonCloseDirective,
  FormControlDirective,
  OffcanvasBodyComponent,
  OffcanvasComponent,
  OffcanvasHeaderComponent,
  OffcanvasTitleDirective,
  SearchButtonComponent
} from '@coreui/angular';

@Component({
  selector: 'docs-search-button-offcanvas',
  templateUrl: './search-button-offcanvas.component.html',
  imports: [
    ButtonCloseDirective,
    FormControlDirective,
    OffcanvasBodyComponent,
    OffcanvasComponent,
    OffcanvasHeaderComponent,
    OffcanvasTitleDirective,
    SearchButtonComponent
  ]
})
export class SearchButtonOffcanvasComponent {
  readonly visible = signal(false);

  onTrigger(): void {
    this.visible.set(true);
  }
}
<c-search-button
  (trigger)="onTrigger()"
  aria-controls="search-button-offcanvas"
  aria-label="Open search panel"
  shortcut="meta+shift+o,ctrl+shift+o"
/>

<c-offcanvas [(visible)]="visible" id="search-button-offcanvas" placement="end">
  <c-offcanvas-header>
    <h5 cOffcanvasTitle>Search panel</h5>
    <button (click)="visible.set(false)" aria-label="Close" cButtonClose class="text-reset"></button>
  </c-offcanvas-header>
  <c-offcanvas-body>
    <input aria-label="Search in panel" cFormControl class="mb-3" placeholder="Search..." type="search" />
    <p class="mb-0">Use this space for filters, recent searches, or command shortcuts.</p>
  </c-offcanvas-body>
</c-offcanvas>

Keyboard behavior

When the configured shortcut is pressed

KeyAction
Enter / Space on a focused search buttonTrigger the component activation callback
Configured shortcut, e.g. ⌘/ / Ctrl+/Trigger the component activation callback
Modifier key inside the visible shortcutAdd .active to the corresponding .search-button-key while pressed
Final key inside the visible shortcutAdd .active to the corresponding .search-button-key while pressed

Keyboard state behavior

InteractionEffect
Matching shortcut on keydownOptionally prevents the browser’s default behavior and emits (trigger)
Plain typing inside input, textarea, select, or contenteditableDoes not trigger the component without meta or ctrl
keyup after a shortcut key pressRemoves .active from the rendered shortcut keys
Browser window blurClears all active shortcut key states
Multiple configured shortcutsThe component listens to all configured shortcuts and renders the platform-preferred one in the UI

Accessibility

Accessibility is an important part of the Search Button design. The component includes built-in behaviors that help preserve expected keyboard interaction and reduce conflicts with assistive technologies, but accessible results still depend on choosing the right markup and shortcut combinations.

Built-in accessibility behavior

  • Native button semantics are preserved because <c-search-button> renders a <button type="button"> internally.
  • Rendered .search-button-keys are treated as visual hints only and are hidden from assistive technologies.
  • Plain typing inside editable fields does not trigger the component unless the shortcut also includes meta or ctrl.
  • The component keeps standard button keyboard behavior such as Enter and Space.

Author responsibilities

  • Choose shortcuts carefully and avoid overriding common browser or system shortcuts unless that behavior is intentional and clearly communicated.
  • Make sure the visible button label clearly describes the action, for example Search, Open search, or Command palette.
  • Provide a custom icon template via <ng-template cTemplateId="icon"> marked aria-hidden="true" when the default icon isn’t suitable.

Customizing

CSS variables

Angular Search Button uses local CSS variables on .search-button for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.

--cui-search-button-height: #{$search-button-height};
--cui-search-button-padding-x: #{$search-button-padding-x};
--cui-search-button-font-family: #{$search-button-font-family};
--cui-search-button-font-size: #{$search-button-font-size};
--cui-search-button-font-weight: #{$search-button-font-weight};
--cui-search-button-color: #{$search-button-color};
--cui-search-button-bg: #{$search-button-bg};
--cui-search-button-border-width: #{$search-button-border-width};
--cui-search-button-border-color: #{$search-button-border-color};
--cui-search-button-border-radius: #{$search-button-border-radius};
--cui-search-button-box-shadow: #{$search-button-box-shadow};
--cui-search-button-transition: #{$search-button-transition};
--cui-search-button-focus-color: #{$search-button-focus-color};
--cui-search-button-focus-bg: #{$search-button-focus-bg};
--cui-search-button-focus-border-color: #{$search-button-focus-border-color};
--cui-search-button-focus-box-shadow: #{$search-button-focus-box-shadow};
--cui-search-button-icon-size: #{$search-button-icon-size};
--cui-search-button-keys-gap: #{$search-button-keys-gap};
--cui-search-button-key-width: #{$search-button-key-width};
--cui-search-button-key-height: #{$search-button-key-height};
--cui-search-button-key-padding-inline: #{$search-button-key-padding-inline};
--cui-search-button-key-font-size: #{$search-button-key-font-size};
--cui-search-button-key-bg: #{$search-button-key-bg};
--cui-search-button-key-border-radius: #{$search-button-key-border-radius};
--cui-search-button-key-active-bg: #{$search-button-key-active-bg};
--cui-search-button-placeholder-margin-inline: #{$search-button-placeholder-margin-inline};

How to use CSS variables

const vars = {
  '--cui-search-button-bg': 'var(--cui-tertiary-bg)',
  '--cui-search-button-color': 'var(--cui-body-color)',
  '--cui-search-button-border-color': 'var(--cui-primary)',
}
<c-search-button [ngStyle]="vars"></c-search-button>

SASS variables

$search-button-height:              $input-height !default;
$search-button-padding-x:           $input-padding-x !default;
$search-button-font-family:         $input-font-family !default;
$search-button-font-size:           $input-font-size !default;
$search-button-font-weight:         $input-font-weight !default;
$search-button-color:               $input-placeholder-color !default;
$search-button-bg:                  $input-bg !default;
$search-button-border-width:        $input-border-width !default;
$search-button-border-color:        $input-border-color !default;
$search-button-border-radius:       $input-border-radius !default;
$search-button-box-shadow:          $input-box-shadow !default;
$search-button-transition:          $input-transition !default;

$search-button-focus-color:         $input-focus-color !default;
$search-button-focus-bg:            $input-focus-bg !default;
$search-button-focus-border-color:  $input-focus-border-color !default;
$search-button-focus-box-shadow:    $input-focus-box-shadow !default;

$search-button-icon-size:           1.125rem !default;

$search-button-keys-gap:            .25rem !default;
$search-button-key-width:           1.5rem !default;
$search-button-key-height:          1.5rem !default;
$search-button-key-padding-inline:  .25rem !default;
$search-button-key-font-size:       .75rem !default;
$search-button-key-bg:              var(--#{$prefix}tertiary-bg) !default;
$search-button-key-border-radius:   var(--#{$prefix}border-radius-sm) !default;
$search-button-key-active-bg:       var(--#{$prefix}secondary-bg) !default;

$search-button-placeholder-margin-inline:  .55rem 2rem !default;

API reference

SearchButton Module

import { SearchButtonModule } from '@coreui/angular';

@NgModule({
  imports: [SearchButtonModule,]
})
export class AppModule() { }

c-search-button

component

jsx
import { SearchButtonComponent } from '@coreui/angular'

Props

PropertyDefaultType
disabledfalseboolean

Toggle the disabled state for the component.

placeholder'Search'string

Placeholder content rendered inside .search-button-placeholder.

preventDefaulttrueboolean

Prevent the browser's default behavior when the configured shortcut matches.

shortcut'meta+/,ctrl+/'string

Comma-separated shortcut list. The component matches all configured shortcuts and renders the platform-preferred one.

Events

Event name
trigger

Event emitted when the component is activated by click or keyboard shortcut.

  • $event void