WebberUI

Smooth Caret Input

彈簧物理平滑游標輸入框:自訂游標以 spring 滑行跟隨文字位置,支援直條/方塊/底線三款形狀。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

650
42
<SmoothCaretInput />

安裝

npx shadcn@latest add https://webberui.com/r/smooth-caret-input.json

安裝時會一併寫入 --wb-duration-fast--wb-ease-out CSS 變數到你的全域樣式。

安裝依賴後,從 registry JSON(/r/smooth-caret-input.jsonfiles[0].content)複製 smooth-caret-input.tsx 原始碼到你的 components/ui/ 目錄,並在全域 CSS 加入:

npm install motion clsx tailwind-merge
:root {
  --wb-duration-fast: 200ms;
  --wb-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

使用

import { SmoothCaretInput } from "@/components/ui/smooth-caret-input";

<SmoothCaretInput
  placeholder="開始輸入⋯"
  onChange={(value) => console.log(value)}
/>

受控模式:

const [value, setValue] = React.useState("");

<SmoothCaretInput value={value} onChange={setValue} caretShape="block" />

Props

Prop型別預設值說明
valuestring受控值;省略時元件內部自管(非受控)
defaultValuestring""非受控模式的初始值
onChange(value: string) => void值變更時觸發
placeholderstring佔位文字
disabledbooleanfalse停用輸入
caretShape"bar" | "block" | "underline""bar"游標形狀
caretColorstring文字色游標顏色(任意 CSS 顏色)
stiffnessnumber650彈簧剛性,越大越快貼合
dampingnumber42彈簧阻尼,越大回彈越少
namestringinput 的 name,供表單提交
idstringinput 的 id,供 label 綁定
aria-labelstringplaceholder無障礙標籤

細節

  • 彈簧跟隨:以隱藏鏡像 span 量測游標前文字寬度換算像素位置,交由 useSpring 平滑滑行到目標位置
  • 游標移動偵測:監聽 selectionchange,方向鍵、點擊、選取都會即時重算並暫停閃爍,滑行結束後恢復閃爍
  • 溢出處理:文字超出寬度而水平捲動時,扣除 scrollLeft 讓游標維持在可視區
  • IME 安全:注音/拼音組字期間鏡像會納入組字文字,游標位置持續正確跟隨

可及性

  • 自訂游標帶 aria-hidden,不干擾螢幕報讀;input 承接 aria-labelnameid
  • 使用者系統開啟「減少動態效果」時,掛載後改回原生游標並停用彈簧與閃爍動畫
  • 未提供 aria-label 時自動採用 placeholder,確保有可讀名稱

On this page