# @nativescript/input-accessory Keyboard input accessory — docked input bar, interactive dismiss, and auto-scroll on both iOS and Android. Commonly used with chat interfaces, search focused views, or anywhere you want a keyboard-attached input experience. ## Features - **iOS**: Moves your input bar into a [inputAccessoryView](https://developer.apple.com/documentation/uikit/uiresponder/inputaccessoryview) docked to the keyboard with system blur effect, interactive dismiss via scroll gesture, and smooth keyboard transitions (like iMessage) - **Android**: Uses [WindowInsetsAnimationCompat](https://developer.android.com/reference/androidx/core/view/WindowInsetsAnimationCompat) for smooth keyboard transitions with `translationY` animation, interactive swipe-to-dismiss, and scroll padding management (API 30+) - **Auto-growing input**: Automatically resizes the accessory as the [TextView](https://docs.nativescript.org/ui/text-view) content grows (up to a configurable max height) - **Auto-scroll**: Scrolls to bottom when the keyboard appears; maintains scroll position when it hides - **Any layout**: Use any NativeScript view markup for your input bar — the plugin handles the keyboard docking ## Installation ```bash npm install @nativescript/input-accessory ``` ## Usage - one `ScrollView` for content - one input container at the bottom - one `TextView` - call `setup(...)` after views are loaded - call `updateAccessoryHeight()` on `textChange` - call `cleanup()` on teardown ### Core (XML + TypeScript) ```xml ``` ```ts import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild, inject } from '@angular/core'; import { EventData, Page, ScrollView, TextView, View } from '@nativescript/core'; import { InputAccessoryManager } from '@nativescript/input-accessory'; @Component({ selector: 'chat', templateUrl: './chat.component.html' }) export class ChatComponent implements AfterViewInit, OnDestroy { @ViewChild('scrollView', { read: ElementRef }) scrollView!: ElementRef; @ViewChild('inputContainer', { read: ElementRef }) inputContainer!: ElementRef; private page = inject(Page); private manager: InputAccessoryManager | null = null; private textView: TextView | null = null; ngAfterViewInit() { setTimeout(() => this.setup(), 0); } onTextViewLoaded(args: EventData) { this.textView = args.object as TextView; this.setup(); } onTextChange() { this.manager?.updateAccessoryHeight(); } dismissKeyboard() { this.manager?.dismissKeyboard(); } ngOnDestroy() { this.manager?.cleanup(); } private setup() { if (this.manager || !this.textView || !this.scrollView?.nativeElement || !this.inputContainer?.nativeElement) return; this.manager = new InputAccessoryManager(); this.manager.setup({ page: this.page, scrollView: this.scrollView.nativeElement, inputContainer: this.inputContainer.nativeElement, textView: this.textView, }); } } ``` ### Solid ```tsx import { onCleanup, onMount } from 'solid-js'; import { Page, ScrollView, TextView, View } from '@nativescript/core'; import { InputAccessoryManager } from '@nativescript/input-accessory'; export function Home() { let pageRef: Page; let scrollRef: ScrollView; let inputRef: View; let textRef: TextView; const manager = new InputAccessoryManager(); onMount(() => { manager.setup({ page: pageRef, scrollView: scrollRef, inputContainer: inputRef, textView: textRef }); }); onCleanup(() => manager.cleanup()); return ( manager.updateAccessoryHeight()} />