Repository navigation
feat(web): labs toggle + workspace editing affordances (0282) - #412
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Grab handle + ghost on panel headers (flag-gated); a slot-drag lifecycle store lights up ALL docks while dragging — closed docks materialize as labeled edge strips, so drops land anywhere; landing flash; Move menu on DropdownMenu (kills the popover dismissal race); diff-driven aria-live announcer + focus restoration covering every mutation road. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
workspace.customize renders every dock as a labeled slot of draggable view chips (tier toggle, hide, Move menu intact); Esc/Done exits with a save-as nudge when the tree changed; entries in the palette, workspace switcher, Move menus and Labs; grab-handle coachmark on first run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…0282) Positional insertSlot in the workspace layout primitives (moveSlot = insert-at-end); slot.reorder up/down palette commands per view; drop-edge insertion indicator on arrange-mode chips (TabBar's pattern). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…oggle Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
|
Preview removed for PR #412. |
| setDropEdge(event.clientX < rect.left + rect.width / 2 ? 'before' : 'after') | ||
| }} | ||
| onDragLeave={() => setDropEdge(null)} | ||
| onDrop={(event) => { |
| } | ||
|
|
||
| /** One view as a draggable, editable chip. */ | ||
| function ViewChip({ |
| .map((placement, index) => ({ placement, index })) | ||
| .filter(({ placement }) => placement.tier !== 'hidden') | ||
|
|
||
| const onDrop = (event: DragEvent) => { |
| * animation, so reduced-motion needs no special casing; the flash uses | ||
| * the same mechanism and simply appears/disappears without motion). | ||
| */ | ||
| function DockDropDress({ region, children }: { region: RegionId; children: ReactNode }) { |
| * without it, "pop this out and slot it in over there" silently no-ops | ||
| * (0282's one mechanical bug). Dropping opens the dock with the view. | ||
| */ | ||
| function DockEdgeStrip({ region }: { region: RegionId }) { |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
🖼️ UI changes in this PRScreensAuto-captured by CI · run. Informational — not a blocking check. |
crs48
added a commit
that referenced
this pull request
Jul 8, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @xnetjs/plugins@0.7.0 ### Minor Changes - [#412](#412) [`a5813fc`](a5813fc) Thanks [@crs48](https://github.com/crs48)! - `insertSlot(tree, viewId, region, index)` joins the workspace layout primitives (exploration 0282): positional insertion for within-dock reorders and cross-region moves; `moveSlot` is now insert-at-end. Purely additive. ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/abuse@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/abuse@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 ## @xnetjs/cli@0.0.12 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/runtime@0.1.8 - @xnetjs/data@0.7.0 - @xnetjs/sqlite@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/crypto@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/core@0.7.0 ## @xnetjs/data@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/storage@0.7.0 - @xnetjs/sqlite@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/data-bridge@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/sqlite@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/history@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/identity@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/react@0.7.0 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/runtime@0.1.8 - @xnetjs/history@0.7.0 - @xnetjs/data-bridge@0.7.0 - @xnetjs/data@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/runtime@0.1.8 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/history@0.7.0 - @xnetjs/data-bridge@0.7.0 - @xnetjs/data@0.7.0 - @xnetjs/storage@0.7.0 - @xnetjs/sync@0.7.0 - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/storage@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/sqlite@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/sync@0.7.0 ### Patch Changes - Updated dependencies []: - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 - @xnetjs/core@0.7.0 ## @xnetjs/core@0.7.0 ## @xnetjs/sqlite@0.7.0 ## xnet-cloud@0.0.10 ### Patch Changes - Updated dependencies []: - @xnetjs/crypto@0.7.0 - @xnetjs/cloud@0.0.1 ## @xnetjs/brain@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/vectors@0.0.1 ## @xnetjs/comms@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/crypto@0.7.0 ## @xnetjs/dashboard@0.0.11 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/react@0.7.0 - @xnetjs/data@0.7.0 - @xnetjs/social@0.0.11 ## @xnetjs/labs@0.0.11 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/data@0.7.0 ## @xnetjs/licenses@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/crypto@0.7.0 ## @xnetjs/maps@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 ## @xnetjs/meetings@0.0.4 ### Patch Changes - Updated dependencies [[`a5813fc`](a5813fc)]: - @xnetjs/plugins@0.7.0 - @xnetjs/data@0.7.0 ## @xnetjs/server@0.0.10 ### Patch Changes - Updated dependencies []: - @xnetjs/data-bridge@0.7.0 - @xnetjs/data@0.7.0 - @xnetjs/identity@0.7.0 - @xnetjs/crypto@0.7.0 ## @xnetjs/social@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 - @xnetjs/crypto@0.7.0 ## @xnetjs/unreal@0.0.11 ### Patch Changes - Updated dependencies []: - @xnetjs/data@0.7.0 ## xnet-desktop@0.7.0 Desktop shell release riding the @xnetjs/core 0.7.0 train. Desktop-specific changes are not tracked here; see the core packages' changelogs for what shipped.
crs48
added a commit
that referenced
this pull request
Jul 8, 2026
…e real signal (0283) (#414) Implements docs/explorations/0283 — CI failure patterns and pipeline health. Over the last ~500 Actions runs, ~75% of failures came from four causes unrelated to code correctness, while the one real breakage (Electron Release) went unnoticed in the noise. ## Tier 1 — stop the bleeding - **mobile-e2e.yml**: quoted the two `run:` lines whose `: ` made the file unparseable — GitHub emitted a phantom failed run *on every push* (48/48 failures, ~40% of all failure volume). - **audiotee `Package.swift`**: deployment floor `.macOS(.v14)` → `.macOS("14.2")` (`AudioHardwareCreateProcessTap` is 14.2+). Every Electron Release macOS build since 0279 failed on this; verified locally with `swift build -c release`. Runtime capability selection already gates on darwin ≥ 23.4 before probing the helper. - **Fallow**: removed from PR CI entirely (user decision — stronger than the exploration's report-only option). Weekly schedule + manual dispatch keep the hard `--fail-on-issues` gate; turbo cache re-enabled. It was the slowest job (~17 min) and failed 44% of PR runs on advisory notes. - **visual-capture**: job-level `continue-on-error` so the self-described informational check can't red a PR. ## Tier 2 — prevent the classes - **actionlint 1.7.12** in the required `lint` job + guarded pre-commit pass (shellcheck severity floor `warning` in both). Fixed what it flags: untrusted `head.ref` inlined in ai-changeset.yml (moved to env), unquoted command substitutions in schema-check.yml, unused loop vars. - **`.husky/prepare-commit-msg`**: dependency-free DCO auto-sign-off (survives `--no-verify`; merges/squashes untouched). DCO failed 76% of recent runs. - **`scripts/check-storybook-shim.mjs`** (`pnpm check:storybook-shim`): walks the story import graph with storybook's own alias map and fails the `lint` job in seconds when the plugins shim misses a name — the drift that broke Visual UI Capture in 0279, 0280, and #412. Backfills `ImporterContribution`. - **plugins-registry.yml**: daily rebuild now refreshes a standing `plugins-registry/data` PR (signed off, `skip-changelog`) instead of pushing to protected `main`, which repo rules rejected every time. ## Tier 3 — ratchets - **Native Helpers workflow**: path-filtered `macos-14` `swift build` on PRs touching `apps/electron/native/**`, so availability drift surfaces pre-release. - **`scripts/changelog/assert-fragment.mjs`** Stop-hook nudge (mirrors the changesets hook): one-shot turn-end reminder when app/package source changed without a changelog fragment. ## Deferred (calendar-gated, unchecked in the doc) - Adding DCO to required checks after ≥1 week of green. - Two-week failure-rate re-measurement. Expected outcome: failed-run rate drops from ~21% to ~2-3%, and a red ✗ regains meaning. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This branch was previously deployed
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.



Implements
0282_[x]_WORKSPACE_EDITING_AFFORDANCES_AND_LABS_TOGGLE.md— making 0280's workspace editing discoverable without flipping the default.What landed
apps/web/src/lib/labs.ts) renders honest toggles for the threexnet:experiment:*flags, with staging badges and a "Reload to apply" chip. Named Labs because the habit tracker owns "Experiments". The Appearance→Workspaces row points here when the malleable shell is off.cursor: grabon panel headers (flag-gated so legacy shells stay inert); a slot-drag lifecycle store lights up all docks while dragging — closed docks materialize as labeled edge strips, fixing the "drops silently no-op" mechanical bug; drag ghost + 40% source opacity; 700ms landing ring; the Move menu rebuilt on DropdownMenu (kills the 0280 popover click-swallow race); a tree-diffSlotAnnouncergives every mutation road (drag/menu/⌘K/agent) the samearia-liveannouncement + landing flash + focus restoration.Workspace: Customize layout…renders the shell as a schematic — four labeled dock slots, every view a draggable chip with tier toggle, hide control, and the Move menu; hidden tray; Esc/Done exits (Esc claims the ladder rung before docks close); a changed tree earns a "Save as…" nudge into the 0280 switcher. Entries: ⌘K, workspace switcher, Move menus, Labs.insertSlot(tree, viewId, region, index)in@xnetjs/plugins(minor, purely additive;moveSlot= insert-at-end),slot.reorder:*palette commands, and TabBar-style insertion indicators on arrange chips.Verified live (worktree preview, real UI events only)
Fresh-profile enable path entirely through UI (Labs toggle → reload chip → arrange); flag-off renders zero drag affordances; header drag lit both closed docks as edge strips and the open dock as a ringed target, drop onto a closed dock moved the view, opened the dock and announced "Explorer moved to right dock"; Move menu executed 5/5 consecutive clicks; arrange mode moved a chip into the empty corner dock, reordered console→first with the insertion indicator visible, surfaced the exit nudge, and saved the arrangement as a workspace node that survived reload; quiet posture kept its summon hot-zones intact alongside arrange mode.
Deliberate non-moves per the doc: no default flip, no DnD library (menu road remains the touch/a11y fallback), no docking compass.
Implements and checks off
docs/explorations/0282_[x]_WORKSPACE_EDITING_AFFORDANCES_AND_LABS_TOGGLE.md.🤖 Generated with Claude Code