Field Notes
Jun 5, 2026 · Updated 9 days ago
We used to blog about how to code. Now it's time to blog the decision. I've been thinking about writing field notes for a long time. The term used to be observing other people, but this is about observing my own thoughts.
I'll share some revamping and improvement across projects I worked on here.
Chat Context Menu
This is a crucial part of LobeHub. It carries all context except the message. But with many things off.

- Ambiguous function: what does
Show Formatting Toolbardo? Will this open a new dialog? (It's actually a checkbox) - Icon color swap based on state: Information overload.
- Mixed trailing arrow icons
→ / ▶︎ - Progressive exposure: why is
Add Skillsparallel withSkills, whileView More Filesis not parallel withUpload File or Image. - Wording: "Upload File or Image" should be "Attachment".
- File name truncation: only truncating the trailing part. Should truncate the middle part.
After all these problem fixed:

The rules are:
- Consistant & clean wording
- Information structure & progressive explosure
- Consistency over tuning
Janky Transition
This is the major transition in Detail. People click on a detail card to see more about the detail. Watch in 0.5x to observe closer.
Originally I put layout on the card and it animates its own size and position. The contents drift along a slightly different path, arriving a beat early or late. Nothing is technically broken, yet the eye reads it as "off" instantly.
// DetailItem.tsx — the dialog frame
const layoutTransition = {
layout: { type: "spring", stiffness: 320, damping: 32, mass: 0.6 },
};
<motion.article layout transition={layoutTransition} />
// DetailItemHeader.tsx — title on a near-but-different spring
const titleTransition = {
layout: { type: "spring", stiffness: 320, damping: 30, mass: 0.7 }, // ← not the frame's
};
<motion.h3 layout transition={{ ...titleTransition, scale }} />
// ...and everything else just falls back to the default spring
<motion.p layout /> {/* summary */}
<motion.div layout /> {/* tags */}
<motion.div layout /> {/* media (DetailItemMedia.tsx) */}
The cause is that Framer Motion animates every layout element on its own independent spring. Leave the transition off and it falls back to the default; hand-tune each one, and they each run slightly different physics. The frame travels on one curve while its children travel on five others.
The fix is to make everything move on the same spring. So I pulled the spring out into a single constant and handed that exact transition to every animated element in the expand:
// animations.ts — one spring, shared by everything in the expandexport const DETAIL_LAYOUT_SPRING = { type: "spring", stiffness: 320, damping: 32, mass: 0.6,};export const DETAIL_LAYOUT_TRANSITION = { layout: DETAIL_LAYOUT_SPRING };// DetailItem.tsx — the dialog frameconst layoutTransition = { layout: { type: "spring", stiffness: 320, damping: 32, mass: 0.6 },};<motion.article layout transition={layoutTransition} /><motion.article layout transition={DETAIL_LAYOUT_TRANSITION} />// DetailItemHeader.tsx — title, summary, tagsconst titleTransition = { layout: { type: "spring", stiffness: 320, damping: 30, mass: 0.7 },};<motion.h3 layout transition={{ ...titleTransition, scale }} /><motion.p layout /><motion.div layout /> {/* tags */}<motion.h3 layout transition={{ ...DETAIL_LAYOUT_TRANSITION, scale }} /><motion.p layout transition={DETAIL_LAYOUT_TRANSITION} /><motion.div layout transition={DETAIL_LAYOUT_TRANSITION} /> {/* tags */}// DetailItemMedia.tsx — media<motion.div layout /><motion.div layout transition={DETAIL_LAYOUT_TRANSITION} />The revamped version feels like this:
The article frame, the media, the title, the summary, the tag row, and each tag chip now share one physics simulation, so they accelerate, travel, and settle together, riding the frame as a single object. The takeaway is small but general: for coordinated layout animations, consistency beats tuning.
Privacy Warning Dialog
The major problem here is wording.

The first time I saw the dialog, I almost immediately skipped it — no hook, no real reminder, just a warning that no one likes to read.

Chat Sharing
🚧 This section is WIP
My collegue handle this to me to "polish details". This feature allows people to select multiple messages and forward to another agent. At the first glance, I spotted many problems
- The bottom toolbar is taking too much vertical space which is more important here becuase we hope people can see more messages in one screen
- Agent title and avatar combo is repeating in every message, eating more vertical spaces
- "Select to here" is ambiguous: from where to where?
- Text hirechy error in the Forward panel
- Calling people "User" and calling AI "Assistant"

IM Channel Configuration
🚧 This section is WIP
The constraints here:
- We really need many boring fields per the platform's guideline
Usage Screen
🚧 This section is WIP
Timeline Extension
Here we are showing a Twitter browsing history list.
It used to be a one-column layout. I realized that one column is for focusing on each post, but people come here to quickly find a certain post, so I switched to a masonry layout.
The search bar was originally a show-off widget, back in 2022 when I was building it. So I reverted it to a common, familiar pattern.
The original icon is semantic but ugly: restore your Twitter home page. The revamped one kept the Twitter bird home element but added some offset.

More Before / After
Here are more comparisons. Try adjusting the handle to see what's changed.

BeforeAfter
BeforeAfter
If there's more works worth sharing, I'll write a second one.
No content is written by AI in this essay.