react-focus-input-z
v2.1.0
Published
Tiny headless React input helper for better focus UX. Zero config, no provider.
Maintainers
Readme
🎯 react-focus-input-z
react-focus-input-z: is a tiny React input helper you reach for when you’re lazy but still want decent UX 😴✨
Simple, focused, and zero-configuration.
🚀 Why react-focus-input-z?
- Automatic focus handling (first initFocused wins)
- Controlled input friendly
- Works with native
<input /> - Minimal API, easy drop-in replacement
- No Provider, no context
- Small bundle size
📦 Installation
npm install react-focus-input-z⚡ Quick Example
1️⃣ Basic usage (lazy default)
import { useState } from "react"
import FocusInput from "react-focus-input-z"
export default function App() {
const [value, setValue] = useState("")
return (
<FocusInput
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Focus me"
/>
)
}
2️⃣ Multiple inputs (smart initial focus)
export default function App() {
return (
<>
<label>
Username:
<FocusInput placeholder="Enter username" />
</label>
<label style={{ marginLeft: 20 }}>
Email:
<FocusInput
placeholder="Enter email"
initFocused
/>
</label>
</>
)
}
If multiple inputs have initFocused, only the first mounted one will receive focus.
3️⃣ Explicit focus control (optional)
import { useRef } from "react"
import FocusInput, {
IFocusInputRef,
} from "react-focus-input-z"
export default function App() {
const ref = useRef<IFocusInputRef>(null)
return (
<>
<FocusInput
ref={ref}
placeholder="Click button to focus"
/>
<button onClick={() => ref.current?.focus()}>
Focus input
</button>
</>
)
}
🧩 Using with UI libraries (Ant Design example)
react-focus-input-z renders a native. <input />
To integrate with UI libraries like Ant Design, simply reuse their input styles.
import { Form, Button } from "antd"
import FocusInput from "react-focus-input-z"
export default function App() {
return (
<Form layout="vertical" style={{ maxWidth: 400 }}>
<Form.Item label="Username">
<FocusInput
placeholder="Enter username"
className="ant-input"
/>
</Form.Item>
<Form.Item label="Email">
<FocusInput
placeholder="Enter email"
initFocused
className="ant-input"
/>
</Form.Item>
<Button type="primary">Submit</Button>
</Form>
)
}Optional: match AntD focus style
.ant-input {
height: 32px;
padding: 4px 11px;
font-size: 14px;
border-radius: 6px;
border: 1px solid #d9d9d9;
}
.ant-input:focus {
border-color: #1677ff;
box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.2);
}🪝 useFocusInput – Full example
import { useRef, useState } from "react"
import {
useFocusInput,
IFocusInputRef,
} from "react-focus-input-z"
export default function App() {
const ref = useRef<IFocusInputRef>(null)
const [value, setValue] = useState("Hello")
const focus = useFocusInput(
undefined, // no global focusId
true, // initFocused (first wins)
ref // imperative ref
)
return (
<div style={{ padding: 24, maxWidth: 320 }}>
<label style={{ display: "block", marginBottom: 8 }}>
Username
</label>
<div
style={{
border: "1px solid #d9d9d9",
borderRadius: 6,
padding: 4,
boxShadow: focus.focused
? "0 0 0 2px rgba(22,119,255,.2)"
: "none",
}}
>
<input
{...focus.getInputProps({
value,
onChange: (e) => setValue(e.target.value),
placeholder: "Type here",
style: {
width: "100%",
border: "none",
outline: "none",
padding: "4px 8px",
},
})}
/>
</div>
<div style={{ marginTop: 12 }}>
<button onClick={() => ref.current?.focus()}>
Focus
</button>
<button
style={{ marginLeft: 8 }}
onClick={() => ref.current?.blur()}
>
Blur
</button>
</div>
<div style={{ marginTop: 8, fontSize: 12 }}>
Focused: {String(focus.focused)}
</div>
</div>
)
}
useFocusInputdoes not render UI. It only manages focus logic and returns helpers to bind into your own input.
🧠 What this example shows
- ✅ useFocusInput without global store (focusId)
- ✅ initFocused (auto focus on mount)
- ✅ Imperative API: focus() / blur()
- ✅ Custom wrapper + focus style
- ✅ Controlled input
- ✅ No Provider, no Context
⚙️ Props
All standard HTMLInput props are supported.
| Prop | Type | Description |
| ------------- | -------------------------- | ---------------------------------- |
| value | string | Controlled input value |
| onChange | (e: ChangeEvent) => void | Change handler |
| initFocused | boolean | Focus on mount (only one wins) |
| className | string | Custom class |
| ref | IFocusInputRef | Imperative focus / blur (optional) |
🧠 Design Philosophy
- This is not a design system
- This is not headless UI
- This is not trying to be flexible
It’s a lazy-day utility:
“I just want the input to feel nicer.”
📤 Public API
- FocusInput (default export)
- useFocusInput (advanced / headless)
📜 License
MIT
