Inline Edit
NewCustomize
Medium
Min width180px
Save
Radius10px
Save delay600ms
Installation
npx shadcn@latest add https://uibrik.com/r/inline-edit.jsonInstall the packages
npm install @tabler/icons-react motionAdd the cn helper
Imports
cnfrom@/lib/utils, whichshadcn initcreates. Add it by hand without shadcn.Copy the source into your project
components/uibrik/inline-edit/inline-edit.tsx"use client"; import { IconCheckFilled, IconCircleCheckFilled, IconLoader2, IconPencilFilled, IconXFilled } from "@tabler/icons-react"; import { AnimatePresence, animate, motion, useMotionValue, useReducedMotion, type AnimationPlaybackControls, } from "motion/react"; import { useEffect, useLayoutEffect, useRef, useState, type FocusEvent, type KeyboardEvent, type PointerEvent } from "react"; import { cn } from "@/lib/utils"; const SPRING = { type: "spring", duration: 0.42, bounce: 0 } as const; // One type scale for both states, so the text never moves or resizes when the // label turns into an input. const SIZES = { sm: { text: "text-sm", height: 32, pad: 8, icon: 14, button: 28 }, md: { text: "text-[15px]", height: 36, pad: 10, icon: 15, button: 32 }, lg: { text: "text-2xl font-semibold tracking-[-0.02em]", height: 48, pad: 12, icon: 18, button: 36 }, } as const;
Adds the files to
components/uibrik/inline-edit and installs @tabler/icons-react and motion. With the @uibrik namespace set up: npx shadcn@latest add @uibrik/inline-edit.Usage
import { InlineEdit } from "@/components/uibrik/inline-edit/inline-edit";<InlineEdit label="…" size="md" minWidth={180} blurBehavior="save" selectOnEdit required={false} radius={10} defaultValue="" placeholder="Empty" disabled={false} // value="…" // onChange={(value) => {}} // maxLength={0}/>Props
InlineEdit- size
- Type "sm" | "md" | "lg"
- "md"
- Type size. The label and the input share it, so nothing moves when editing starts.
- minWidth
- Type number
- 180
- Width the field opens to at least while editing.
- blurBehavior
- Type "save" | "cancel"
- "save"
- What clicking away does with the draft.
- selectOnEdit
- Type boolean
- true
- Select the whole value when editing starts, instead of placing the caret at the end.
- required
- Type boolean
- false
- Refuse to save an empty value: the field shakes and stays open.
- radius
- Type number
- 10
- Corner radius of the field.
- labelrequired
- Type string
- –
- Accessible name, e.g. "Project name".
- value / onChange
- Type string / (value) => void | Promise
- –
- Controlled value. Return a promise from onChange to show a saving state; a rejection shakes the field and keeps it open.
- defaultValue
- Type string
- ""
- Starting value when uncontrolled.
- placeholder
- Type string
- "Empty"
- Shown, muted, when the value is empty.
- maxLength
- Type number
- –
- Longest value the input accepts.
- disabled
- Type boolean
- false
- Show the value without letting it be edited.
- className
- Type string
- –
- Classes for the wrapper.