Skip to main content
← Blog

Rows Before Data — Notes from a Polishing Day

VauDium·

Some days you build features; some days you polish. Three layout jumps, three unexplained inconsistencies, and one hidden bug exposed by making a list shorter — the grammar I found in a day of polish.

Rows Before Data — Notes from a Polishing Day

Some days you build features; some days you polish. This week, a big rework of the Table view filters was followed by a polishing day. Polish doesn’t get planned as a list. The material comes from actually using the screens until something makes you go “wait, what?” — you fix it on the spot and move to the next one. By the end of the day, the fixes turned out to share a grammar.

Anatomy of a Layout Jump

The first “wait, what?” was the task creation modal. Every time it opened, the screen jumped once. Tracing it down, the assignee row was the culprit. It was conditioned to appear only after the project’s member list arrived from the server, so the modal opened, and half a beat later the row barged in and pushed everything below it down.

The funny part: the two rows right above it — project and milestone — were already doing it right. Always rendered, disabled when there’s nothing to show. Only the assignee row had drifted from that grammar. I brought it in line and seeded “me” into the list before members load, and now the modal opens fully formed on its first frame.

The same day I found variations of this in the suggestion dropdown and the template list: items without a project had an empty second line, the title stuck to the top, and their height differed from items with a project. Same prescription: fix the text area’s height, and vertically center a single line. Row height should be decided by design, not by whatever data happens to show up.

One line for the shared principle: rows must exist before data. Data can be late, or absent. The skeleton of the screen should be complete on the first frame anyway, and data merely fills it in as it arrives. fecit already had a rule — “no full-screen spinner on entry; frame first, then content” — and what I learned is that the same rule applies not just to screens but to a single row.

Unexplained Differences Are Bugs

The second batch was colors and sizes.

On mobile, someone (my own eyes, actually) reported that the “Steps” section header looked paler than other section headers in the read-only view. I suspected the text color — wrong. All the text was identical; on that one screen, the header bar’s background was one shade lighter. Four screens out of five agreed and one didn’t, so the answer lived in that one.

The About modals had the opposite problem: their height tracked the body text, so every subject opened a differently sized window. I fixed the height and let short bodies absorb into whitespace, long ones into scroll. The template-picker modals for tasks and memos had also drifted apart — different headers, different item shapes — so I unified them under one grammar.

Difference itself isn’t bad. Intentional difference is design. The problem is unexplained difference. If “why is this one lighter?” has no answer, that’s not personality — that’s a bug.

The Bug I Caught by Making Things Smaller

The template list felt too long, so I cut the page size from twenty items to ten. Then came the report: scrolling stopped working.

The next-page load was wired to the scroll event. With compact items and only ten of them, the list no longer overflowed its container — and a list that doesn’t overflow never fires a scroll event, so the second page could never load. At twenty items the list happened to always overflow, which is why nobody noticed for months.

The fix is auto-replenishment: after each render, check “not overflowing yet, and more exists?” and fetch until the content spills, then hand off to the scroll trigger. Polishing didn’t break the feature — shrinking exposed an assumption that was always there. “This list is always taller than the screen” was written nowhere, but the code was standing on it.

The Rhythm of a Polishing Day

Nothing fixed that day needed a design document. All of it came from using the screens, and most fixes took an hour or two. But without days like this, the “wait, what?” moments accumulate into the product’s impression. Users don’t know the assignee row’s render condition — they know the modal jumps.

Polish material doesn’t come from a backlog; it comes from real use. I still haven’t found better QA than the builder using their own product daily. “We’re building fecit with fecit” is, before it’s a slogan, our bug tracker.