Image Upload Components — Alternatives Considered
A-01: Avatar rewrite to compose ImageDisplay (deferred)
Section titled “A-01: Avatar rewrite to compose ImageDisplay (deferred)”Context: Both Avatar and ImageDisplay render images with
loaded/loading/error states and initials-based placeholders. Reimplementing
Avatar as a thin wrapper over ImageDisplay would consolidate both paths.
Decision: Keep Avatar as-is. Only extract getInitials to a shared
utility (minor modification).
Rationale:
Avataris circular with size variants;ImageDisplayis rectangular. MakingImageDisplayshape-agnostic requires adisplayShapeparameter that adds complexity with no immediate consumer.- Risk of subtle visual regressions in a widely-used component mid-project.
ImageDisplayneeds to be battle-tested in grid and form contexts first.
Revisit trigger: User profile image editing use case. See
follow-up-work.md.
A-02: Controlled-only ImageInspectorOverlay (rejected)
Section titled “A-02: Controlled-only ImageInspectorOverlay (rejected)”Context: The initial implementation only supported controlled mode
(open + onClose as required props). Every consumer had to manage
open/close state.
Alternative: Keep controlled-only, document the pattern as the standard consumer contract.
Decision: Add uncontrolled mode (omit open to get internal state +
trigger button).
Rationale: Inconsistent with ImageDisplay which manages its own dialog
state. The consumer burden (3 lines of state management per usage site)
compounds across form fields, grid cells, and standalone inspectors.
Uncontrolled mode reduces consumer code without breaking controlled usage.
A-03: ImageFormField with dedicated pencil icon for edit (rejected)
Section titled “A-03: ImageFormField with dedicated pencil icon for edit (rejected)”Context: The initial design had three hover icons: eye (inspect), pencil (edit), and trash (remove).
Decision: Remove the pencil icon. Edit is handled by the underlying
ImageDisplay double-click/Enter interaction.
Rationale: With ImageDisplay managing its own edit flow via
onImageChange + config, a separate pencil button creates two competing
edit affordances on the same element. Users would see a pencil icon but also
discover that double-clicking the image opens the same dialog. The pencil
icon adds confusion without adding capability.
A-04: Single worktree for all runs vs. parallel worktrees per run
Section titled “A-04: Single worktree for all runs vs. parallel worktrees per run”Context: The team-split assessment recommended parallel agents within Runs 2 and 3 using separate worktrees per task.
Decision: Runs were executed sequentially with single worktrees per run. Parallel worktrees were available but not fully utilized.
Rationale: The sequential approach was simpler to coordinate and avoided merge conflicts between parallel agents within the same run. The 46 commits completed in a reasonable timeframe. For larger component sets (30+), parallel execution within runs would be worth the coordination overhead.
A-05: react-easy-crop vs. custom crop implementation
Section titled “A-05: react-easy-crop vs. custom crop implementation”Context: ImagePreviewEditor needs crop/zoom/rotate/pan functionality.
Decision: Use react-easy-crop library.
Rationale: The external libraries assessment (external-libraries-assessment.md)
evaluated this dependency and approved it. Building a custom crop
implementation would have been a significant scope increase for functionality
that react-easy-crop provides out of the box with good React integration
and TypeScript support.
A-06: ImageCellEditor reusing ImageDisplay’s baked-in dialog vs. direct dialog rendering
Section titled “A-06: ImageCellEditor reusing ImageDisplay’s baked-in dialog vs. direct dialog rendering”Context: After ImageDisplay gained baked-in edit flow, ImageCellEditor
could theoretically reuse it instead of directly rendering ImageUploadDialog.
Decision: Keep direct dialog rendering in ImageCellEditor.
Rationale: AG Grid’s cell editor lifecycle requires imperative control
(getValue, stopEditing, isPopup). The editor must open the dialog
immediately on mount and capture the result for AG Grid’s value lifecycle.
This is a fundamentally different interaction pattern than ImageDisplay’s
user-initiated double-click flow. See inconsistencies-audit.md finding #5.
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved