Inline Edit

Edit without navigating away.

Project name

{{unless editing}}

html

<div class="inline-demo" style="--accent:#D9C8F0;">
  <p class="inline-demo__label">Project name</p>
  
  <div class="inline-demo__edit">
    <input class="inline-demo__input" type="text" value="Q3 marketing site" />
    <button type="button" class="inline-demo__icon-btn" aria-label="Save">&#10003;</button>
    <button type="button" class="inline-demo__icon-btn" aria-label="Cancel">&times;</button>
  </div>
  
  {{unless editing}}
  <button type="button" class="inline-demo__display">Q3 marketing site <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M16 3l5 5-11 11H5v-5z" /></svg></button>
  

tailwind

<div style="width:280px;font-family:system-ui,sans-serif;color:#241430">
  <p class="m-0 mb-1.5 text-xs font-semibold text-[#241430aa]">Project name</p>
  
  <div class="flex items-center gap-1.5">
    <input type="text" value="Q3 marketing site" class="flex-1 px-2.5 py-2 rounded-md border-[1.5px]" style="border-color:#D9C8F0" />
    <button type="button" aria-label="Save" class="w-[30px] h-[30px] rounded-md border-0 cursor-pointer" style="background:#D9C8F0">&#10003;</button>
    <button type="button" aria-label="Cancel" class="w-[30px] h-[30px] rounded-md border-0 cursor-pointer" style="background:#D9C8F0">&times;</button>
  </div>
  
  {{unless editing}}
  <button type="button" class="inline-flex items-center gap-2 border-0 bg-transparent font-semibold cursor-pointer text-[#241430] py-1">Q3 marketing site <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#D9C8F0" stroke-width="2" aria-hidden="true"><path d="M16 3l5 5-11 11H5v-5z" /></svg></button>
  

react

import { useState } from "react";

export function InlineEdit({
  label = "Project name",
  value: initialValue = "Q3 marketing site",
  editing: initialEditing = true,
  accent = "#D9C8F0",
}) {
  const [editing, setEditing] = useState(initialEditing);
  const [value, setValue] = useState(initialValue);
  return (
    <div style={{ width: 280, fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430" }}>
      <p style={{ margin: "0 0 6px", fontSize: 12, fontWeight: 600, color: "#241430aa" }}>{label}</p>
      {editing ? (
        <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
          <input type="text" value={value} onChange={(e) => setValue(e.target.value)} style={{ flex: 1, padding: "8px 10px", borderRadius: 7, border: "1.5px solid " + accent, font: "inherit" }} />
          <button type="button" aria-label="Save" onClick={() => setEditing(false)} style={{ width: 30, height: 30, borderRadius: 7, border: "none", background: accent, cursor: "pointer" }}>&#10003;</button>
          <button type="button" aria-label="Cancel" onClick={() => setEditing(false)} style={{ width: 30, height: 30, borderRadius: 7, border: "none", background: accent, cursor: "pointer" }}>&times;</button>
        </div>
      ) : (
        <button type="button" onClick={() => setEditing(true)} style={{ display: "inline-flex", alignItems: "center", gap: 8, border: "none", background: "transparent", fontWeight: 600, cursor: "pointer", color: "#241430", padding: "4px 0" }}>
          {value} <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={accent} strokeWidth="2" aria-hidden="true"><path d="M16 3l5 5-11 11H5v-5z" /></svg>
        </button>
      )}
    </div>
  );
}