Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GoogleChromeLabs/ProjectVisBug
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: RoleModel/ProjectVisBug
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 10 commits
  • 65 files changed
  • 3 contributors

Commits on Aug 27, 2026

  1. route style edits through a store so they can be undone and exported

    Every feature wrote `el.style[prop] = value` directly, which made two
    things impossible: recording a before/after for undo, and exporting
    usable CSS instead of a page full of inline styles.
    
    Introduce app/core as the single funnel. editStyle() writes the
    declaration into an editor-owned stylesheet keyed by a generated class
    and hands a change record to the history journal. Selectors repeat the
    class three times (0,3,0) so the rule beats most author CSS without
    resorting to !important, which would be noise in an export.
    
    history.js journals DOM moves, attributes and text alongside styles, so
    duplicate, delete, group/ungroup and keyboard nudges all undo. Rapid
    edits coalesce on an idle window, and beginGesture/endGesture collapses
    a continuous drag into one entry. Bound to cmd+z / cmd+shift+z.
    
    Overlays and drag ghosts keep their inline styles — isEditorChrome()
    keeps ephemeral UI out of the journal and out of exports.
    
    Export falls out cheaply now that edits live in a real stylesheet:
    /export, /export css strip the editor's bookkeeping and emit the markup
    alongside the rules.
    
    Existing tests asserted against el.style, so they read the authored
    value back through the new readStyle helper.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Hunter-Kendall and claude committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    f75e6f9 View commit details
    Browse the repository at this point in the history
  2. snap dragged elements into place using the drop container's layout

    Dragging used to call swapElements(), which exchanged two siblings. It
    could not insert between them, could not cross into another container,
    refused to run when the element had no siblings, and never once looked
    at the parent's display — flex, grid and block all behaved identically.
    
    dropzones.js resolves a real insertion point from the container's
    layout: a caret along the main axis of a flex container (honouring
    row-reverse and grouping wrapped items into lines), a cell in a grid, a
    line-aware caret in inline flow, row/cell insertion in tables, and free
    XY placement with edge snapping for absolutely positioned elements.
    Empty containers now accept drops. It is pure geometry — move.js
    applies the result.
    
    For block and inline containers the axis is measured rather than read
    off `display`: a block container full of inline-block children lays out
    as a row, and trusting display alone drew the caret on the wrong axis.
    
    Grid distinguishes the two cases. An auto-flow grid reorders in the DOM
    and lets the browser re-place, preserving auto-placement; a grid whose
    children are explicitly placed pins the dragged element to the cell.
    
    move.js drives this with pointer events instead of HTML5 drag-and-drop,
    for precise coordinates and control over the overlay. A 4px threshold
    keeps a plain click selecting rather than dragging, and the whole
    gesture commits as one undo entry. Keyboard nudging is unchanged.
    
    visbug-insertion draws the caret and cell highlight. It needs
    `inset: … auto auto …` to escape the popover UA styles that would
    otherwise centre it in the viewport, matching the other overlays, and
    joins isOffBounds so it never becomes its own drop target.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Hunter-Kendall and claude committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    8ecf992 View commit details
    Browse the repository at this point in the history
  3. add an export button that saves the page as one HTML and one CSS file

    Export existed only as a search command, and it emitted just the editor's
    own rules — the page's stylesheets stayed behind as <link> tags pointing
    at the origin, so a saved file looked unstyled offline.
    
    collectCSS() now gathers everything that styles the page: inline <style>
    blocks, same-origin links, @import-ed sheets, adopted stylesheets, and
    cross-origin sheets whose cssRules throw and have to be fetched instead.
    media="print" links are wrapped in @media so their scope survives, and
    url()s are rewritten against their own sheet's URL so images and fonts
    still resolve from the saved copy. The editor's rules go last so they win.
    
    The HTML gets the same treatment: src/href/srcset resolved to absolute,
    editor markup and bookkeeping attributes dropped. Scripts are stripped —
    an export is a snapshot of how the page looks now, and left in place the
    page's own scripts re-run on open and rebuild the DOM out from under it,
    VisBug's bundle included.
    
    The button sits in a new actions row under the colors. Saving two files
    makes Chrome ask once to allow multiple downloads; /export single still
    folds the CSS into a <style> tag for one self-contained file.
    
    Two fixes found while testing: the editor stylesheet was emitted twice,
    because the dedup compared pretty-printed text against cssText and never
    matched — it now skips by identity. And the toolbar, already taller than
    a 1366x768 viewport before this row, cut the new button off entirely, so
    it tightens up on short screens rather than putting items out of reach.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Hunter-Kendall and claude committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    d64efcd View commit details
    Browse the repository at this point in the history
  4. replace the download button with one that copies the edits as a prompt

    Downloading a flattened page is the wrong shape for getting design changes
    back into a codebase — nobody wants a 5000-line stylesheet, they want to
    know which elements changed and what happened to them.
    
    The hard part isn't listing the edits, it's naming the element each one
    belongs to in a way that survives the trip from a rendered page back to
    source. No single selector does that: an nth-child path is unique but says
    nothing about which component owns it, a class is meaningful but may repeat,
    a test id is decisive but often absent. So every element ships with each
    anchor we can establish — test attribute, id, css selector, opening tag,
    text, ancestor trail, dom path — ordered by how well they tend to map onto
    code, and the agent picks whichever fits the codebase in front of it. The
    css selector falls back to an id-scoped nth-child so it stays unique without
    losing the container's name.
    
    changes.js records only what a thing looked like *before* VisBug touched it.
    The net change is worked out at report time against what's authored now, so
    forty arrow-key nudges read as one change and anything undone drops out on
    its own — replaying the journal would have reported both.
    
    Anchors are cleaned through the DOM rather than by regex, so no data-vb-id,
    generated class, grab cursor or empty style attribute leaks into text that
    is meant to look like source.
    
    Downloading is still available as /export; the prompt is also on /copy
    changes. Capturing originals moved to edit.js, which breaks the import cycle
    that would otherwise exist between changes.js and style-store.js.
    
    Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
    Hunter-Kendall and claude committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    194816a View commit details
    Browse the repository at this point in the history
  5. read the page's design tokens and use them when editing padding, marg…

    …in, font, box-shadow, and color
    
    VisBug's nudges were pure px arithmetic, which fights a page built on a
    token scale. app/core/tokens.js discovers a page's own CSS custom
    properties (or Optics' specifically, via a cross-origin-safe probe),
    groups the ones that form a scale, and lets margin/padding/font/box-shadow
    step through them instead of by raw pixels — shift is the escape hatch
    back to px. Margin/padding measurement overlays now read as the token
    name (e.g. --op-space-medium) when a value lands exactly on a scale step.
    Color picking gets a matching swatch list drawn from the page's palette.
    
    Also fixes a race in extension/visbug.js where color-mode/scheme
    preferences could be sent before toolbar/inject.js had registered its
    listener on first launch, and extracts that send into
    extension/contextmenu/send.js so it's handled once instead of at each
    call site.
    
    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
    Hunter-Kendall and claude committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    a01156f View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    39efc5d View commit details
    Browse the repository at this point in the history
  7. group the copy-changes button with the color swatches

    Moves the copy-prompt button into the same <ol colors> as the
    foreground/background/border swatches so it reads as one group, and
    swaps its bespoke circle styling for the shared color-swatch look.
    Hunter-Kendall committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    a363929 View commit details
    Browse the repository at this point in the history
  8. updated prompt copy

    Hunter-Kendall committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    6f73830 View commit details
    Browse the repository at this point in the history
  9. fix text tool bug

    Hunter-Kendall committed Aug 27, 2026
    Configuration menu
    Copy the full SHA
    8d55725 View commit details
    Browse the repository at this point in the history

Commits on Sep 8, 2026

  1. Merge pull request #1 from RoleModel/christmas-bullet

    Undoable, exportable edits with layout- and token-aware editing
    Hunter-Kendall authored Sep 8, 2026
    Configuration menu
    Copy the full SHA
    bb011b8 View commit details
    Browse the repository at this point in the history
Loading