Skip to content

feat: position support opt-in, tests, docs (#645, #646, #647, #648) - #657

Merged
ViewFromTheBox merged 2 commits into
feature/css-positioningfrom
feature/640-position-supports-tests-docs
Jul 14, 2026
Merged

ViewFromTheBox merged 2 commits into
feature/css-positioningfrom
feature/640-position-supports-tests-docs

Conversation

@ViewFromTheBox

@ViewFromTheBox ViewFromTheBox commented Jul 14, 2026 •

Copy link
Copy Markdown
Member

Description

Closes out the #640 umbrella with the four remaining sub-issues:

Also carries a small UX cleanup: the Position panel's local breakpoint tab strip is gone — the top-bar viewport switcher already drives the same shared active-breakpoint store, so the local tabs were duplicate UI. The panel still reads the active breakpoint and re-renders effective values / "Inherited" hints as the top-bar switches.

Closes: #645, #646, #647, #648

Type of Change

  • New feature (adds new functionality)
  • Enhancement (improves existing functionality) — panel de-dup

Related Issue

Issue: #640 (umbrella); #645, #646, #647, #648 (sub-issues)

Motivation and Context

The core positioning machinery landed in #656 (feature branch parent). This PR completes the umbrella by turning it on for every artisanpack block that makes sense, backing it with round-trip test coverage, and giving downstream developers a docs page to follow.

Changes Made

How Has This Been Tested?

Testing Environment:

  • Operating System: macOS Darwin 25.5
  • Browser: Chrome (via Herd local dev)
  • PHP Version: 8.4.3
  • Project Version: v1.4 (development)

Tests Performed:

  1. Manual smoke pass on multiple block types in the dev app (Group, Column, Buttons, etc.) — Position panel renders, values apply in the canvas, top-bar viewport switcher re-renders the panel's effective values correctly.
  2. Confirmed the panel no longer shows its own breakpoint tabs after the removal.
  3. Automated suites (below).

Accessibility Tests Run

  • Keyboard navigation tested (Position panel controls remain tab-reachable)
  • ARIA labels checked (SelectControl / UnitControl / NumberControl inherit WP's a11y contracts)
  • No regression from the tab-strip removal — the top-bar switcher owns that role already
  • Screen reader tested (not exhaustive)

Tests Added

  • Unit tests added/updated
  • Integration tests added/updated
  • All tests passing

Test details:

  • JS: 4 new integration tests → 38 positioning tests total (34 previously + 4 new), all green.
  • Full JS suite unchanged pre-existing failure count (18 in site-editor-app.test.tsx — localStorage under jsdom, unrelated to this branch).
  • PHP suite untouched (no PHP changes in this PR).

Documentation

  • Inline code documentation added
  • README updated
  • Wiki updated (new docs/position.md linked from docs/home.md)
  • API documentation updated

Pre-Submission Checklist

  • Followed contributing guidelines
  • Checked for other open PRs for same update
  • Code passes all tests
  • Accessibility tests completed (see above)
  • Code follows project style guide (block.json edits preserve original 4-space indentation via Python json.dumps(indent=' '))
  • Self-review completed
  • Comments added for complex code
  • No new warnings generated

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added CSS positioning controls across supported blocks, including responsive offsets, stacking order, and position modes.
    • Added inherited-value guidance and warnings for absolute positioning without a positioned ancestor.
    • Position controls now follow the editor’s active viewport selection.
  • Documentation

    • Added comprehensive positioning guidance, troubleshooting information, and a new Position topic to the block documentation.
  • Tests

    • Added integration coverage for responsive behavior, inheritance, legacy values, and CSS output.

, #646, #647, #648)

Closes out the #640 umbrella by (1) flipping the position opt-in
on every top-level artisanpack block, (2) shipping integration +
e2e coverage, and (3) documenting the feature. Also removes the
duplicate breakpoint switcher from the Position panel — the
top-bar viewport switcher already drives it via the shared
active-breakpoint store.

## Changes

### #645 — 82 artisanpack blocks opt in

Bulk-added `"position": true` to `supports` in every
`resources/js/visual-editor/blocks/*/block.json` that doesn't declare
a `parent` or `ancestor` restriction. Twenty child-only blocks
(accordion internals, list items, `column` inside `columns`, `button`
inside `buttons`, `post-template` inside `query`, pagination pieces)
are deliberately skipped — positioning a child that a container relies
on for layout breaks the container's contract.

`artisanpack/group` already carried Gutenberg's
`supports.position: { sticky: true }` object shape; `positionEnabled()`
accepts both `true` and any truthy object, so it was left alone.

### #646 — no-op given the I7 cutover

This repo replaces `registerCoreBlocks()` with `registerArtisanPackBlocks()`
(I7 · #415). No `core/*` block enters the editor, so a filter injecting
position support into core containers would be dead code. Every
container listed in the parent issue (`core/group`, `core/columns`,
`core/column`, `core/cover`, `core/row`, `core/stack`, `core/grid`,
`core/buttons`, `core/image`) has an `artisanpack/*` fork covered by
#645.

### #647 — integration + e2e coverage

- **Integration (Vitest, real):** `resources/js/visual-editor/positioning/__tests__/integration.test.ts`
  round-trips the full resolver → merger → emitter chain across all
  five Tailwind breakpoints, verifies raw vs. effective readers,
  legacy sticky no-churn, and the static-toggle-preserves-orphan-fields
  flow. 4 new tests, 38 positioning tests total green.
- **E2E (Playwright shape, commented):** `tests/E2E/positioning.spec.ts`
  documents five runtime scenarios — sticky group on canvas scroll,
  absolute cover inside a positioned parent, ancestor warning when
  the parent is static, per-breakpoint viewport switching, legacy
  sticky frontend render. Follows the `animations.spec.ts`
  precedent — activated when the Playwright runner lands.

### #648 — docs

New `docs/position.md` covering opt-in, attribute shape, position
values, offset units, per-breakpoint inheritance, the ancestor
warning, the two frontend emission channels (inline + `<style
data-ve-position>`), and a troubleshooting section. Linked from
`docs/home.md`.

### Panel cleanup — remove duplicate breakpoint switcher

The Position panel had its own `<Base | Mobile | Tablet | Desktop |
xl+ | 2xl+>` tab strip that flipped the shared active-breakpoint
store. The top-bar viewport switcher already drives that store —
the panel's local tabs were a second control for the same job.
Removed the tab strip; the panel reads `activeBreakpoint` via
`useSyncExternalStore` and re-renders effective values / "Inherited"
hints when the top-bar switches. Docs updated to note the panel
follows the top-bar switcher.

## Tests

- 38 positioning JS tests (34 unit + 4 new integration) — green.
- Full JS suite: 2809 passed / 18 pre-existing failures (site-editor
  `localStorage` under jsdom, unrelated). No new regressions from
  the 82 block.json edits.

Closes #645, #646, #647, #648

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e5f28e91-fa00-4aa9-974a-0ef23778b42b

📥 Commits

Reviewing files that changed from the base of the PR and between d7bbc84 and b90d131.

📒 Files selected for processing (89)
  • CHANGELOG.md
  • docs/home.md
  • docs/position.md
  • resources/js/visual-editor/blocks/accordions/block.json
  • resources/js/visual-editor/blocks/archives/block.json
  • resources/js/visual-editor/blocks/audio/block.json
  • resources/js/visual-editor/blocks/author-social-icons/block.json
  • resources/js/visual-editor/blocks/avatar/block.json
  • resources/js/visual-editor/blocks/breadcrumbs/block.json
  • resources/js/visual-editor/blocks/buttons/block.json
  • resources/js/visual-editor/blocks/callout/block.json
  • resources/js/visual-editor/blocks/categories/block.json
  • resources/js/visual-editor/blocks/code/block.json
  • resources/js/visual-editor/blocks/columns/block.json
  • resources/js/visual-editor/blocks/comment-author-avatar/block.json
  • resources/js/visual-editor/blocks/comment-author-name/block.json
  • resources/js/visual-editor/blocks/comment-content/block.json
  • resources/js/visual-editor/blocks/comment-date/block.json
  • resources/js/visual-editor/blocks/comment-edit-link/block.json
  • resources/js/visual-editor/blocks/comment-reply-link/block.json
  • resources/js/visual-editor/blocks/comments-number/block.json
  • resources/js/visual-editor/blocks/comments-pagination/block.json
  • resources/js/visual-editor/blocks/comments/block.json
  • resources/js/visual-editor/blocks/copyright/block.json
  • resources/js/visual-editor/blocks/cover/block.json
  • resources/js/visual-editor/blocks/details/block.json
  • resources/js/visual-editor/blocks/embed/block.json
  • resources/js/visual-editor/blocks/file/block.json
  • resources/js/visual-editor/blocks/form/block.json
  • resources/js/visual-editor/blocks/gallery/block.json
  • resources/js/visual-editor/blocks/grid/block.json
  • resources/js/visual-editor/blocks/heading/block.json
  • resources/js/visual-editor/blocks/icon/block.json
  • resources/js/visual-editor/blocks/image/block.json
  • resources/js/visual-editor/blocks/latest-posts/block.json
  • resources/js/visual-editor/blocks/list/block.json
  • resources/js/visual-editor/blocks/loginout/block.json
  • resources/js/visual-editor/blocks/marquee/block.json
  • resources/js/visual-editor/blocks/media-text/block.json
  • resources/js/visual-editor/blocks/navigation/block.json
  • resources/js/visual-editor/blocks/next-post/block.json
  • resources/js/visual-editor/blocks/paragraph/block.json
  • resources/js/visual-editor/blocks/post-author-biography/block.json
  • resources/js/visual-editor/blocks/post-author-name/block.json
  • resources/js/visual-editor/blocks/post-author/block.json
  • resources/js/visual-editor/blocks/post-comments-count/block.json
  • resources/js/visual-editor/blocks/post-comments-form/block.json
  • resources/js/visual-editor/blocks/post-comments-link/block.json
  • resources/js/visual-editor/blocks/post-comments-title/block.json
  • resources/js/visual-editor/blocks/post-content/block.json
  • resources/js/visual-editor/blocks/post-date/block.json
  • resources/js/visual-editor/blocks/post-excerpt/block.json
  • resources/js/visual-editor/blocks/post-featured-image/block.json
  • resources/js/visual-editor/blocks/post-navigation-link/block.json
  • resources/js/visual-editor/blocks/post-terms/block.json
  • resources/js/visual-editor/blocks/post-title/block.json
  • resources/js/visual-editor/blocks/post-types-search-results/block.json
  • resources/js/visual-editor/blocks/preformatted/block.json
  • resources/js/visual-editor/blocks/previous-post/block.json
  • resources/js/visual-editor/blocks/pullquote/block.json
  • resources/js/visual-editor/blocks/query-title/block.json
  • resources/js/visual-editor/blocks/query/block.json
  • resources/js/visual-editor/blocks/quote/block.json
  • resources/js/visual-editor/blocks/read-more/block.json
  • resources/js/visual-editor/blocks/related-posts/block.json
  • resources/js/visual-editor/blocks/search-field/block.json
  • resources/js/visual-editor/blocks/search-filters-buttons/block.json
  • resources/js/visual-editor/blocks/search-filters-taxonomy/block.json
  • resources/js/visual-editor/blocks/search-filters/block.json
  • resources/js/visual-editor/blocks/search/block.json
  • resources/js/visual-editor/blocks/separator/block.json
  • resources/js/visual-editor/blocks/single-content/block.json
  • resources/js/visual-editor/blocks/site-logo/block.json
  • resources/js/visual-editor/blocks/site-tagline/block.json
  • resources/js/visual-editor/blocks/site-title/block.json
  • resources/js/visual-editor/blocks/skills-slider/block.json
  • resources/js/visual-editor/blocks/social-share-content/block.json
  • resources/js/visual-editor/blocks/spacer/block.json
  • resources/js/visual-editor/blocks/table/block.json
  • resources/js/visual-editor/blocks/tabs/block.json
  • resources/js/visual-editor/blocks/tag-cloud/block.json
  • resources/js/visual-editor/blocks/template-part/block.json
  • resources/js/visual-editor/blocks/term-description/block.json
  • resources/js/visual-editor/blocks/verse/block.json
  • resources/js/visual-editor/blocks/video/block.json
  • resources/js/visual-editor/positioning/__tests__/integration.test.ts
  • resources/js/visual-editor/positioning/with-position-control.tsx
  • src/VisualEditorServiceProvider.php
  • tests/E2E/positioning.spec.ts

📝 Walkthrough

Walkthrough

Position support is documented, enabled across in-scope blocks, connected to shared responsive breakpoint state, removed from the service provider’s emitter registration, and covered by integration tests plus commented E2E scaffolding.

Changes

Position support rollout

Layer / File(s) Summary
Position documentation and release notes
CHANGELOG.md, docs/home.md, docs/position.md
Documents the position schema, responsive inheritance, ancestor warnings, CSS output paths, troubleshooting, and supported block topic.
Block position capability opt-ins
resources/js/visual-editor/blocks/*/block.json
Adds supports.position: true across the updated artisanpack block definitions.
Shared responsive breakpoint wiring
resources/js/visual-editor/positioning/with-position-control.tsx, src/VisualEditorServiceProvider.php
Removes local breakpoint tabs and active-breakpoint mutation from the inspector, and removes the scoped PositionEmitter registration.
Position integration and E2E coverage
resources/js/visual-editor/positioning/__tests__/integration.test.ts, tests/E2E/positioning.spec.ts
Tests responsive resolution, legacy values, static output, and preserved fields; adds commented Playwright positioning test scaffolding.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • Issue 640 — Covers the broader CSS positioning feature implemented and documented by this change.
  • Issue 646 — Relates to position support for core container equivalents and artisanpack forks.

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/640-position-supports-tests-docs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Applies the 10 findings from the local /code-review pass on the
initial commit of this PR. No behavior changes to end users beyond
the tab-strip removal from the previous commit (already reviewed and
approved).

## Correctness

- **JSON reformatting churn on 17 block.json files (Angle A #2, Conv #2).**
  Reverted every touched `block.json` to the base branch state, then
  re-inserted `"position": true,` via a text-level regex that only
  adds one line. Diff footprint for the block manifests dropped from
  82 files / 695 insertions / 82 deletions to 82 files / 82
  insertions — one clean line per manifest. Preserves the original
  compact inline arrays (`"keywords": [ "a", "b" ]`, `"align": [
  "wide", "full" ]`, `"enum": [ ... ]`) and keeps git-blame on those
  arrays pointed at the original authors instead of this PR.

- **Stale JSDoc (Angle A #1, Angle B #1).** The `with-position-control.tsx`
  docblock still described the removed tab strip. Rewrote to
  reflect the actual behavior: the panel follows the top-bar
  `ViewportSwitcher` via the shared active-breakpoint store,
  matching every sibling responsive-aware inspector panel.

- **CHANGELOG path case (Angle A #3, Conv #1).** `tests/e2e/positioning.spec.ts`
  → `tests/E2E/positioning.spec.ts` — git tracks the file at the
  uppercase path (matches the `animations.spec.ts` sibling). macOS's
  case-insensitive filesystem hid the mismatch locally.

- **CHANGELOG missing UX note (Angle B #5).** Added a sentence
  explaining that per-breakpoint authoring follows the top-bar
  viewport switcher and no separate control lives in the panel.
  Answers the anticipated support ticket "where did the
  Base/Mobile/Tablet/Desktop buttons in the Position panel go?".

- **Panel-vs-top-bar dependency (Angle A #4, Angle B #3).** Verified
  intentional and consistent with sibling panels; documented in the
  new CHANGELOG sentence and the rewritten JSDoc. No code change —
  the a11y story is handled at the inspector level by
  `InspectorScopeChip` (`role="status" aria-live="polite"`).

## Cleanup

- **Dead `PositionEmitter` DI binding (Angle C #4).** Removed the
  scoped binding from `VisualEditorServiceProvider.php` plus its
  `use` import. `BlockSupports::compilePosition()` instantiates the
  emitter directly with the request-scoped `BreakpointRegistry` —
  no container round-trip needed.

- **`docs/position.md` Related links (Angle A #6).** Switched from
  relative Markdown `[Animations](animations.md)` to wiki-style
  `[[Animations]]`, matching `docs/home.md`.

- **Brittle exact-string assertion (Angle A #5).** Replaced the
  order-and-whitespace-sensitive `.toBe(...)` with individual
  `.toContain(...)` checks in `integration.test.ts`, matching the
  surrounding assertions.

- **`docs/home.md` slash spacing (Conv #3).** `(static/relative/...)`
  → `(static / relative / ...)`, matching the sibling `Linear /
  radial / conic borders` entry directly above.

## Verified out (not fixed)

- **Dynamic blocks miss position CSS on frontend (Angle C #1).**
  `PositionEmitter` IS reached via `BlockSupports::compilePosition()`
  → `compile()` → block partials calling `wrapperAttrs()`. The DI
  binding was dead but the code path is live.
- **`addSaveProps` writes string `style` (Angle C #3).** WordPress's
  `renderToString` (save serialization path) accepts string style
  attributes; user smoke test confirmed frontend renders correctly.
- **`responsive` attribute injection breaks downgrade (Angle C #2).**
  Real forward-only concern for the feature, not a defect in this
  PR.

## Tests

- 38 positioning JS tests + 86 PHP tests, all green.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ViewFromTheBox ViewFromTheBox moved this from Backlog to In Review in ArtisanPack UI Overview Jul 14, 2026
@ViewFromTheBox
ViewFromTheBox marked this pull request as ready for review July 14, 2026 21:53
@ViewFromTheBox
ViewFromTheBox merged commit c569ad3 into feature/css-positioning Jul 14, 2026
1 check passed
@github-project-automation github-project-automation Bot moved this from In Review to Done in ArtisanPack UI Overview Jul 14, 2026
@ViewFromTheBox
ViewFromTheBox deleted the feature/640-position-supports-tests-docs branch July 14, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant