Breaking
- Require Node.js 22 19b5316
- Require React 19.2+ cfaebbb
- Ink now uses
useEffectEvent internally to avoid re-subscribing input handlers on every render
- Pressing Backspace now correctly sets
key.backspace instead of key.delete (#634) 321a2e8
- Most terminals send the same byte for Backspace as the Delete key, which caused Ink to misreport it. If you were checking
key.delete to handle backspace, switch to key.backspace
key.meta is no longer set to true when Escape is pressed e195912
- Previously a backward-compat shim made plain Escape set both
key.escape and key.meta. Now only key.escape is true. key.meta is reserved for actual Alt/Meta modifier combinations
New
- Add
usePaste hook for handling clipboard paste events fbbeb23
- Automatically enables bracketed paste mode so pasted text arrives as a single string, never misinterpreted as individual key presses by
useInput
- Add
useWindowSize hook 7047795
- Returns
{columns, rows} and re-renders automatically on terminal resize
- Add
useBoxMetrics hook for measuring box dimensions at runtime (#433) 88731d1
- Add
useAnimation hook for built-in animation support (#142) ada019c
- Provides a frame counter that increments at a configurable interval, with pause/resume support and automatic cleanup on unmount
- Add
alternateScreen option to render() (#263) 5a60eb9
- Renders into the terminal's alternate screen buffer (like vim or less), restoring the previous terminal content on exit
- Add
interactive option to render() (#888) 02490f6
- Override automatic interactive-mode detection for environments where the built-in heuristic doesn't fit
- Add
activeId to useFocusManager() (#661) eb2f470
- Returns the ID of the currently focused component, or
undefined if nothing is focused
- Add
borderBackgroundColor (and per-side variants) to <Box> (#906) d3c6d14
- Set a background color on borders independently from the box content background
- Add
wrap="hard" to <Text> (#925) 2b1e3a6
- Fills each line to the full column width, breaking words mid-word as needed
- Add
maxWidth and maxHeight props to <Box> (#713) 9291794
- Add
aspectRatio, alignContent, position="static", and top/right/bottom/left layout props to <Box> c2f4b86
- Kitty keyboard protocol: query all terminals in auto mode instead of a hardcoded allowlist (#895) 3e672b5
Fixes
- Fix incremental rendering for trailing newline (#910) c32da0b
- Fix
useInput crash on unmapped key codes (#902) 969a4f1
- Fix CJK text truncation exceeding
<Box> width b5f3e3a
- Fix splitting wide characters (emoji, CJK) when overlapping writes occur (#930) 06d53f4
- Fix dangling
staticNode reference (#905) 0dc4dfa
Migration guide
key.backspace vs key.delete
// Before β physical backspace was reported as key.delete
useInput((input, key) => {
if (key.delete) { /* was catching physical backspace key */ }
});
// After
useInput((input, key) => {
if (key.backspace) { /* physical backspace key (0x7F) */ }
if (key.delete) { /* actual Delete key (e.g. Fn+Backspace) */ }
});
key.meta no longer set on plain Escape
// Before β key.meta was true for both Escape AND Alt+key
useInput((input, key) => {
if (key.meta) { /* fired on plain Escape too */ }
});
// After β check key.escape explicitly for the Escape key
useInput((input, key) => {
if (key.escape) { /* plain Escape */ }
if (key.meta) { /* Alt/Meta combos only */ }
});
v6.8.0...v7.0.0