Skip to content

FE-1660: Explain blocked edits in read-only Petrinaut documents - #9662

Open
kube wants to merge 1 commit into
codex/fe-1659-local-document-urlsfrom
codex/fe-1660-readonly-feedback
Open

FE-1660: Explain blocked edits in read-only Petrinaut documents#9662
kube wants to merge 1 commit into
codex/fe-1659-local-document-urlsfrom
codex/fe-1660-readonly-feedback

Conversation

@kube

@kube kube commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Trying to drag a node or use an editing shortcut on a read-only document shows a brief neutral notice. Repeated attempts reuse the same notice, and normal selection, panning, and zooming stay quiet.

On published examples, Make a local copy in the notice opens an editable copy using the local document URLs from the preceding PR. Other restrictions explain whether to switch to Edit or reset the simulation.

Links

Blocked by

Changes

  • Detect blocked node drags after six pixels of movement, preserving click-to-inspect behavior
  • Explain blocked mutations, commands, and editing shortcuts while preserving permitted scenario edits
  • Add notification IDs for deduplication and an optional action button
  • Map the neutral notification tone to the toast library's supported informational type
  • Expose readOnlyAction for hosts and connect example pages to their local-copy action
  • Update the user guide and integration README, with a patch changeset for @hashintel/petrinaut

Test coverage

  • Petrinaut suite: 857 tests passed; website suite: 463 tests passed
  • New coverage checks drag thresholds, canceled gestures, quiet inspection and panning, blocked shortcuts, mutation restrictions, notice deduplication, focus preservation, and the action button
  • Both packages' builds, type checks, and lints passed; repository formatting and architecture checks passed
  • Browser verification on the local and deployed previews: a blocked place drag showed the notice, and its action opened a new editable local UUID URL that persisted after reload
  • The Turbo execution graph is unchanged

How to test

  • Open /examples/sir-epidemic-model on the website preview
  • Click a place to inspect it, then drag it
  • Confirm one brief read-only notice appears
  • Try N, T, or Delete with a selected node and confirm the document remains unchanged
  • Choose Make a local copy in the notice and edit the new copy

@kube kube self-assigned this Sep 11, 2026
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hash Ready Ready Preview Sep 13, 2026 7:16pm UTC
petrinaut Ready Ready Preview Sep 13, 2026 7:16pm UTC
petrinaut-docs Ready Ready Preview Sep 13, 2026 7:16pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
hashdotdesign-tokens Ignored Ignored Preview Sep 13, 2026 7:16pm UTC

Request Review

@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps labels Sep 11, 2026
@kube
kube added this pull request to stack #9663 September 11, 2026 02:41
@kube
kube marked this pull request as ready for review September 11, 2026 03:03
Copilot AI balanced review requested due to automatic review settings September 11, 2026 03:03
@cursor

cursor Bot commented Sep 11, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
UX and notification plumbing around existing read-only guards; no changes to auth, persistence, or mutation semantics beyond showing feedback when edits are already blocked.

Overview
Blocked edits in Petrinaut now surface a brief neutral toast instead of failing silently. The message depends on why editing is blocked (host readonly, Simulate/Actual mode, or an active simulation), and repeated attempts dedupe via stable notification IDs.

Hosts can pass readOnlyAction on Petrinaut so the notice can include a button (e.g. Make a local copy on published examples). Notifications support optional actions, map the neutral tone to informational toasts, and avoid stealing focus when the action is clicked.

Feedback is wired through useReadOnlyFeedback into blocked mutations, commands (paste, auto-layout), keyboard shortcuts, canvas node drags (after a 6px threshold, preserving click-to-inspect), and toolbar/canvas placement. Allowed scenario edits in Simulate mode stay silent.

Docs and a patch changeset for @hashintel/petrinaut describe the behavior; the example page connects readOnlyAction to its existing fork handler.

Reviewed by Cursor Bugbot for commit 69fc391. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 4c24941. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Address the preview feedback behavior and preserve native undo when no history adapter is configured.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds read-only feedback for blocked Petrinaut edits, including deduplicated notices and optional local-copy actions.

Changes:

  • Detects blocked drags, shortcuts, mutations, and commands.
  • Adds notification actions, deduplication, and contextual messaging.
  • Updates integrations, tests, documentation, README, and changeset.
File summaries
File Description
libs/@hashintel/petrinaut/src/ui/views/SDCPN/use-canvas-interactions.ts Reports blocked canvas mutations.
libs/@hashintel/petrinaut/src/ui/views/SDCPN/renderers/react-flow/react-flow-canvas/use-read-only-node-drag.ts Detects blocked node drags.
libs/@hashintel/petrinaut/src/ui/views/SDCPN/renderers/react-flow/react-flow-canvas/use-read-only-node-drag.test.tsx Tests drag feedback behavior.
libs/@hashintel/petrinaut/src/ui/views/SDCPN/renderers/react-flow/react-flow-canvas.tsx Installs drag handlers.
libs/@hashintel/petrinaut/src/ui/views/Editor/components/BottomBar/use-keyboard-shortcuts.ts Explains blocked shortcuts.
libs/@hashintel/petrinaut/src/ui/views/Editor/components/BottomBar/use-keyboard-shortcuts.test.tsx Tests shortcut feedback.
libs/@hashintel/petrinaut/src/ui/petrinaut.tsx Exposes the read-only action prop.
libs/@hashintel/petrinaut/src/react/state/read-only-action-context.ts Provides host action context.
libs/@hashintel/petrinaut/src/react/notifications/toaster.tsx Renders notification actions.
libs/@hashintel/petrinaut/src/react/notifications/provider.tsx Adds deduplication and informational tone mapping.
libs/@hashintel/petrinaut/src/react/notifications/provider.test.tsx Tests notification behavior.
libs/@hashintel/petrinaut/src/react/notifications/context.ts Extends notification input types.
libs/@hashintel/petrinaut/src/react/hooks/use-read-only-feedback.ts Centralizes read-only notices.
libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-mutations.ts Reports blocked mutations.
libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-mutations.test.tsx Tests mutation feedback.
libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-commands.ts Reports blocked commands.
libs/@hashintel/petrinaut/README.md Documents the host action API.
libs/@hashintel/petrinaut/docs/drawing-a-net.md Documents read-only behavior.
apps/petrinaut-website/src/examples/full-example-page.tsx Connects the local-copy action.
.changeset/smooth-readonly-feedback.md Adds the package changeset.
Review details

Suppressed comments (2)

libs/@hashintel/petrinaut/src/react/hooks/use-petrinaut-commands.ts:35

  • The new behavior in this guard is the notification, but the existing use-petrinaut-commands.test.tsx cases only assert no-op return values and do not provide or inspect NotificationsContext.addNotification. A regression removing notifyReadOnly() here (or at the analogous auto-layout guard on line 44) would therefore leave the command tests green; add blocked paste and auto-layout assertions for the notice.
      if (isReadOnly) {
        notifyReadOnly();
        return { newItemIds: [] };

libs/@hashintel/petrinaut/src/react/hooks/use-read-only-feedback.ts:27

  • The public PetrinautPreview does not provide a usable outcome for this shared feedback hook: without quickSimulation, it renders the canvas without NotificationsProvider (src/ui/preview/petrinaut-preview.tsx:311-345), so the default addNotification is a no-op; with Quick Simulation, the preview's mode is simulate but it intentionally exposes no Edit mode control (src/ui/preview/petrinaut-preview.tsx:321-345, docs/preview.md:64-67), so this message tells users to switch to an unavailable mode. Supply preview-specific notification wiring/copy or keep this feedback scoped to the full editor.
    const message =
      reason.kind === "host-readonly"
        ? "This document is read-only."
        : reason.kind === "simulation-active"
          ? "Reset the simulation to edit this net."
          : "Switch to Edit to change this net.";
    addNotification({
      id: `read-only:${petriNetId}:${reason.kind}`,
      message,
      tone: "neutral",
      durationMs: 4500,
      action: reason.kind === "host-readonly" ? action : undefined,
  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +66 to +68
if (isReadonly) {
notifyReadOnly();
return;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants