- Gallery
- Forms & Input
- Inline Edit
Inline Edit
Click-to-edit fields that transform from text to input on click.
Forms & Inputinlineeditclick-to-editinputtext
Dependencies
Other dependencies:
@/components/ui/input@/components/ui/button
How to use this component
Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.
Code
1"use client";23import { useState } from 'react';4import { Input } from '@/components/ui/input';5import { Button } from '@/components/ui/button';6import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';7import { Pencil, Check, X, User, Mail, Briefcase } from 'lucide-react';89interface EditableFieldProps {10 label: string;11 value: string;12 icon: React.ReactNode;13 onSave: (value: string) => void;14}1516function EditableField({ label, value, icon, onSave }: EditableFieldProps) {17 const [isEditing, setIsEditing] = useState(false);18 const [editValue, setEditValue] = useState(value);1920 const handleSave = () => {21 if (editValue.trim()) {22 onSave(editValue.trim());23 setIsEditing(false);24 }25 };2627 const handleCancel = () => {28 setEditValue(value);29 setIsEditing(false);30 };3132 return (33 <div className={`flex items-center justify-between p-3 rounded-lg transition-colors \` +34 `${isEditing ? 'bg-muted' : 'hover:bg-muted/50 group'}`}>35 <div className="flex items-center gap-3">36 <div className="p-2 bg-primary/10 rounded-lg text-primary">37 {icon}38 </div>39 <div>40 <p className="text-xs text-muted-foreground uppercase tracking-wide">{label}</p>41 {isEditing ? (42 <Input43 value={editValue}44 onChange={e => setEditValue(e.target.value)}45 onKeyDown={e => {46 if (e.key === 'Enter') handleSave();47 if (e.key === 'Escape') handleCancel();48 }}49 className="h-7 w-48"50 autoFocus51 />52 ) : (53 <p className="font-medium">{value}</p>54 )}55 </div>56 </div>57 {isEditing ? (58 <div className="flex items-center gap-1">59 <Button size="sm" variant="ghost" className="h-7 w-7 p-0" onClick={handleSave}>60 <Check className="w-4 h-4 text-green-500" />61 </Button>62 <Button size="sm" variant="ghost" className="h-7 w-7 p-0" onClick={handleCancel}>63 <X className="w-4 h-4 text-red-500" />64 </Button>65 </div>66 ) : (67 <Button68 size="sm"69 variant="ghost"70 className="h-7 w-7 p-0 opacity-0 group-hover:opacity-100"71 onClick={() => setIsEditing(true)}72 >73 <Pencil className="w-4 h-4" />74 </Button>75 )}76 </div>77 );78}7980export default function InlineEdit() {81 const [fields, setFields] = useState({82 name: 'Sarah Johnson',83 email: 'sarah.johnson@example.com',84 role: 'Senior Developer'85 });8687 const updateField = (key: keyof typeof fields, value: string) => {88 setFields(prev => ({ ...prev, [key]: value }));89 };9091 return (92 <Card className="w-full max-w-md mx-auto">93 <CardHeader>94 <CardTitle>User Profile</CardTitle>95 </CardHeader>96 <CardContent className="space-y-2">97 <EditableField98 label="Name"99 value={fields.name}100 icon={<User className="w-4 h-4" />}101 onSave={value => updateField('name', value)}102 />103 <EditableField104 label="Email"105 value={fields.email}106 icon={<Mail className="w-4 h-4" />}107 onSave={value => updateField('email', value)}108 />109 <EditableField110 label="Role"111 value={fields.role}112 icon={<Briefcase className="w-4 h-4" />}113 onSave={value => updateField('role', value)}114 />115 </CardContent>116 </Card>117 );118}