Inspector + chrome bug-fix pass#55
Merged
Merged
Conversation
BareDOM's x-select renders its inner native <select> from the host element's `value` attribute — `<option selected>` on a slotted option is not consulted, because `sync-options!` clones the option nodes into the shadow and then `render!` writes `(set! (.-value select-el) (or value ""))` using the host's attr. Three inspector sites set `selected=""` on the matching option but never mirrored the value onto the host, so the picker painted blank even when the stored value was visible elsewhere in the doc: - `build-placement-field` (the layout placement picker). - `build-multi-enum` (the multi-select shared enum row). - `build-enum` (via `append-enum-options!`). Add the host-value mirror at each site after appending options. The previous PR (#53) accidentally introduced the visible regression on enum rows by routing them through `build-widget-shell` — the shell set the value *before* options existed, which works on the first paint but is fragile against shadow re-renders and never had the explicit post-options mirror the legacy code lacked. Centralising the fix in `append-enum-options!` keeps every enum row honest going forward. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After PR #53's enum host-value mirror, variant pickers painted correctly because x-button's variant is set on insertion. size and type were still blank: x-button declares them with :default "md" / "button", BareDOM uses the default when the attribute is unset, but model/current-value returns nil for absent :attrs entries — so the picker had nothing to display. Lift the display value to `(or stored (:default prop))` inside append-enum-options! (covers every single-select enum row) and mirror the same fallback in build-multi-enum's host-value branch (joint nil + not mixed → show the agreed default). The stored-vs- default distinction was never useful at the display layer — the inspector should match what BareDOM is rendering, which is the default when nothing is explicitly stored. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A free-placement node's :layout :x / :y get their values from (/ (- clientX start-cx) zoom) during a drag, which routinely produces float-precision artefacts like 257.29168701171875. The inspector painted these via (str raw), so the input grew a twelve-decimal tail that the user couldn't ignore. Add `format-decimal` to bareforge.util.coerce — pure helper that rounds a number (or a purely-numeric string) to a configurable number of decimal places (default 2), trims trailing zeros and a trailing decimal point, and passes non-numeric strings (CSS lengths like "50%", compound forms like "10px 20px") through unchanged. Applied in two display sites: - build-free-coord-field: turns 257.29168701171875 into "257.29" and 939.8698120117188 into "939.87". - build-widget-shell: covers every other inspector input that paints a stored value (numeric attrs stored as (str <float>) get the same treatment; existing text/enum values pass through). Storage layer is unchanged on purpose — only display formatting. The underlying float values stay in the doc so undo / export / load-roundtrip semantics don't move. If sub-decimal precision ever becomes load-bearing for a field, callers can pass a higher decimals count. Six new tests pin the rounding contract, the integer / trailing- zero trim, custom precision, numeric-string handling, and CSS- length passthrough. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a node's placement transitions from :flow (or :background) to :free, the layout map gains `:placement :free` but `:x`/`:y` are absent. The reconciler renders the element at its static-position fallback (or wherever absolute-with-no-coords lands it), so the user sees the button where it always was. On the very first drag, `start-from-canvas!` reads `(or (get-in node [:layout :x]) 0)` → 0, captures that as `free-initial-x`, then commits new x = 0 + cursor-delta. The element snaps to the canvas origin plus the drag delta — far from where the user clicked. Fix at promotion time so the layout map is consistent from the moment :free is selected. `commit-promote-placement!` detects the flow → free transition, reads the element's current viewport BCR relative to its rendered parent's BCR, divides by zoom to get content pixels (same math the drag delta uses), and commits placement + x + y in a single state/commit!. The follow-up drag sees real coords and behaves identically to a second drag would. Implemented inside the inspector's `build-placement-field` event handler — that's where DOM access and the doc-op already meet, and the helper stays out of drag.cljs which has no business knowing about inspector picker transitions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The earlier commit (e95e765) captured an element's visual position when its layout was promoted to :free, but two issues remained: 1. The inspector x and y fields painted blank instead of the captured coordinates. `update-fields-in-place!` flowed through `sync-widget-value!` which set the `value` attribute with the raw new-v unchanged — and `desired-widget-value` for layout widgets returns the raw number (a long-tail float) without going through `format-decimal`. The build path uses format-decimal, so the build and patch paths displayed different things. Route sync-widget-value! through format-decimal for non-boolean values, so the patch update shows the same rounded form the initial build does. 2. The captured x/y were off by the parent's border width. CSS `position: absolute; left: X; top: Y;` is measured from the containing block's padding box, not its BCR (which sits at the outer edge of the border). Subtracting the parent's clientLeft / clientTop — the rendered border width — brings the captured offset into the same reference frame the reconciler uses when it re-renders the just-promoted element. Without this a parent with a 1 px border shifts the element 1 px on commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dragging a palette item across other labels paints the labels with the native browser selection highlight, and the highlight survives the drop. Subsequent palette pointerdowns get intercepted by the selection layer (the browser is mid-selection), so the next drag can't start until the user clicks somewhere — typically the search field — to clear the selection. A few palette sub-elements already had `user-select: none` (.palette-category-summary, .palette-item-caret) but the .palette-item itself didn't, so the labels were free-game for selection. Apply `user-select: none` to the base `.panel` rule so every tool panel (palette, layers, inspector) inherits the same anti-selection behaviour on its chrome. Native `<input>` and `<textarea>` elements inside the panels still allow text selection because the user-agent stylesheet overrides user-select for form controls — typing into the inspector search fields and text-areas keeps working. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Six bug fixes from a manual smoke session. All six surfaced from poking at the inspector / palette / drag interaction; each is its own focused commit so a bisect or revert lands at the right scope.
Net change
Test plan
🤖 Generated with Claude Code