InputModality
Signal-based wrapper around Angular CDK's InputModalityDetector. Reactively track the user's current input method (keyboard, mouse, or touch).
Recommended: Use Core Package
If you're not using @angular/cdk in your project, we recommend using inputModality from @signality/core instead. It provides the same functionality without requiring the CDK dependency:
typescript
import { inputModality } from '@signality/core';
import { inputModality } from '@signality/cdk-interop'; See InputModality from core for more details.
CDK Interop Package Required
This utility requires the @signality/cdk-interop and @angular/cdk packages to be installed:
bash
npm install @signality/cdk-interop @angular/cdkUsage
angular-ts
import { Component, computed } from '@angular/core';
import { inputModality } from '@signality/cdk-interop';
@Component({
template: `
<div [class]="'input-mode-' + modality()">
<p>Current input: {{ modality() ?? 'none' }}</p>
<p>Using keyboard: {{ isKeyboard() }}</p>
</div>
`,
})
export class InputDemo {
readonly modality = inputModality();
readonly isKeyboard = computed(() => this.modality() === 'keyboard');
}Parameters
| Parameter | Type | Description |
|---|---|---|
options | InputModalityOptions | Optional configuration (see Options below) |
Options
The InputModalityOptions extends CreateSignalOptions<InputModality> and WithInjector:
| Option | Type | Description |
|---|---|---|
equal | ValueEqualityFn<InputModality> | Custom equality function (see more) |
debugName | string | Debug name for the signal (development only) |
injector | Injector | Optional injector for DI context |
Return Value
Returns a Signal<InputModality> containing the current input modality: 'keyboard', 'mouse', 'touch', or null.
Examples
Touch-optimized UI
angular-ts
import { Component, computed } from '@angular/core';
import { inputModality } from '@signality/cdk-interop';
@Component({
template: `
<nav [class.touch-mode]="isTouch()">
<button [style.padding]="buttonPadding()">Menu</button>
<button [style.padding]="buttonPadding()">Settings</button>
</nav>
`,
})
export class AdaptiveNav {
readonly modality = inputModality();
readonly isTouch = computed(() => this.modality() === 'touch');
// Larger touch targets for touch input
readonly buttonPadding = computed(() =>
this.isTouch() ? '1rem 2rem' : '0.5rem 1rem'
);
}Analytics tracking
angular-ts
import { Component, effect, inject } from '@angular/core';
import { inputModality } from '@signality/cdk-interop';
import { AnalyticsService } from './analytics.service';
@Component({ /* ... */ })
export class AppComponent {
readonly analytics = inject(AnalyticsService);
readonly modality = inputModality();
constructor() {
effect(() => {
const current = this.modality();
if (current) {
this.analytics.setUserProperty('input_modality', current);
}
});
}
}Conditional tooltips
angular-ts
import { Component, computed } from '@angular/core';
import { inputModality } from '@signality/cdk-interop';
@Component({
template: `
<button
[attr.title]="showTooltip() ? 'Click to save' : null"
>
💾
</button>
`,
})
export class SaveButton {
readonly modality = inputModality();
// Only show native tooltips for mouse users
readonly showTooltip = computed(() => this.modality() === 'mouse');
}Type Definitions
typescript
type InputModalityOptions = CreateSignalOptions<InputModality> & WithInjector;
function inputModality(options?: InputModalityOptions): Signal<InputModality>;Related
- focusMonitor — Monitor focus state with origin detection