# useKeyboardInset

> A React hook for the mobile on-screen keyboard: how much of the screen it covers, so bars pinned to the bottom ride above it.

- Type: React hook (Hooks & Utilities)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add use-keyboard-inset`
- Docs: https://wingo-ui.com/components/use-keyboard-inset

## Interaction

Open the demo on a phone and tap the message field: as the keyboard slides up, the composer rides on top of it instead of hiding behind it, and the readout shows the covered height with the open flag lit. Close the keyboard and it settles back to the bottom. On a desktop there is no on-screen keyboard, so the inset stays 0px.

## Installation

```bash
npx wingo-ui@latest add use-keyboard-inset
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/use-keyboard-inset` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `hooks/use-keyboard-inset.ts`

npm dependencies: `npm i motion`

## Usage

```tsx
"use client"

import { motion, useTransform } from "motion/react"
import { useKeyboardInset } from "@/hooks/use-keyboard-inset"

export function Composer() {
  const { inset } = useKeyboardInset()
  const y = useTransform(inset, (v) => -v)

  return (
    <motion.form style={{ y }} className="fixed inset-x-0 bottom-0 z-sticky flex gap-2 bg-background p-3 pb-[max(env(safe-area-inset-bottom),12px)]">
      <input aria-label="Message" placeholder="Write a message" enterKeyHint="send" className="h-11 flex-1 rounded-full bg-foreground/5 px-4 text-base" />
    </motion.form>
  )
}
```

## API

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `threshold?` | `number` | `80` | useKeyboardInset(options?): px of covered viewport below which it does not count as a keyboard (browser bars resizing, the iOS form accessory alone). |
| `cssVar?` | `string` | `""` | Also writes the inset in px to this CSS variable on <html> (e.g. "--keyboard-inset"), for CSS-only consumers: bottom: var(--keyboard-inset, 0px). Removed on unmount; use one writer per variable. |
| `disabled?` | `boolean` | `false` | Stops measuring and reports 0. |
| `returns?` | `{ inset: MotionValue<number>; open: boolean }` |  | inset: the covered height in px, updated as the keyboard animates without re-rendering; lift a bar with style={{ y: useTransform(inset, (v) => -v) }}. open: true while the keyboard is up, re-rendering only when it flips (hide a floating button, drop a tab bar). Both are 0 / false on the server, during hydration, on desktops, while pinch-zoomed and when no text field has focus. |

## Parts

### UseKeyboardInsetOptions (type)

The hook's options: { disabled?: boolean; threshold?: number; cssVar?: string }.

### KeyboardInset (type)

The return value: { inset: MotionValue<number>; open: boolean }.

## Examples

- **Hide the tab bar while typing**: Uses the open flag to slide a bottom tab bar away when the keyboard comes up.
- **CSS variable**: cssVar writes the inset to <html>, so a sticky Pay button lifts with plain CSS.

## See also

- [useScrollState](https://wingo-ui.com/components/use-scroll-state) ([Markdown](https://wingo-ui.com/components/use-scroll-state.md))
- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))
- [Bottom Tab Bar](https://wingo-ui.com/components/bottom-tab-bar) ([Markdown](https://wingo-ui.com/components/bottom-tab-bar.md))
- [Sticky CTA Bar](https://wingo-ui.com/components/sticky-cta-bar) ([Markdown](https://wingo-ui.com/components/sticky-cta-bar.md))
- [Chat Thread](https://wingo-ui.com/components/chat-thread) ([Markdown](https://wingo-ui.com/components/chat-thread.md))

---

Canonical: https://wingo-ui.com/components/use-keyboard-inset
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
