Skip to content

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

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

kube wants to merge 2 commits 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

Before this PR, Petrinaut ignored edits on a read-only net without a word. A dragged node stayed put and editing shortcuts did nothing.

A blocked drag, shortcut, paste or delete now shows one brief notice saying why. Hosts can add a button to the read-only notice, and published examples on the website offer Make a local copy there.

9662.mp4

Links

Changes

Petrinaut

  • useReadOnlyFeedback explains a blocked edit

    Message follows the read-only reason: host read-only, Simulate or Actual mode, or a simulation holding the net.
    Repeated attempts show one notice per net and reason.

  • Node drags on a read-only canvas notify after 6 px of movement

    Clicks, panning and zooming stay silent.

  • Mutation guards, paste, auto-layout and the N, T, Delete and undo shortcuts notify

    Scenario and metric edits allowed in Simulate stay silent.

  • readOnlyAction prop adds a button to the host read-only notice

    It travels in NetManagement with the other host-owned net actions.

  • Notifications take an optional id and action

    A notification on screen under the same id is not shown again.

  • Neutral notifications render

    Ark shows only its own toast types, so neutral maps to info.

  • Notifications leave with their editor

    Notifications share one store across the editors on a page.
    Unmounting an editor now removes its notifications, so the read-only notice does not reappear on the editable copy.

Website

  • Example pages pass Make a local copy as their read-only action

Test coverage

  • use-read-only-node-drag.test.tsx:

    Drag threshold, quiet selection and panning, cancelled gestures.

  • use-keyboard-shortcuts.test.tsx:

    Blocked shortcuts notify, typing and selection shortcuts stay quiet.

  • use-petrinaut-mutations.test.tsx:

    Allowed scenario mutations in Simulate stay quiet.

  • provider.test.tsx:

    One notice per id, action button, focus stays on the trigger, nothing left for the next editor.

  • Verified in a browser against the dev server:

    Dragging a node on an example shows the notice with Make a local copy.

How to test

  • Open Petrinaut preview on Vercel
  • Click a place

    Expect selection, no notice

  • Drag the place

    Expect one "This document is read-only." notice with Make a local copy

  • Select a node and press Delete

    Expect net unchanged

  • Notice > Make a local copy

    Expect editable copy at a new /local/<id> URL

@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 Oct 9, 2026 8:28pm UTC
petrinaut Ready Ready Preview Oct 9, 2026 8:28pm UTC
petrinaut-docs Ready Ready Preview Oct 9, 2026 8:28pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
hashdotdesign-tokens Ignored Ignored Preview Oct 9, 2026 8:28pm 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
Additive UX and notification plumbing across editor interactions; scenario edits in Simulate remain allowed and behavior is covered by new tests.

Overview
Blocked edits on read-only nets now surface a deduplicated neutral toast with a reason-specific message (host read-only, wrong mode, or active simulation) instead of failing silently.

useReadOnlyFeedback drives notices from mutation/command guards, keyboard shortcuts (paste, delete, add-node keys, undo), canvas node-drop, and a new 6px drag threshold on the React Flow pane so clicks and panning stay quiet. Hosts can pass readOnlyAction on <Petrinaut>; the action appears only for host read-only, and example pages wire Make a local copy.

Notifications gain optional id (skip if already visible) and action buttons; neutral tone maps to Ark info. Unmounting an editor remove()s toasts so notices do not leak to another instance on the page.

Reviewed by Cursor Bugbot for commit d326e68. 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.

Stale Bugbot comment from a previous run.

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;
@kube
kube force-pushed the codex/fe-1660-readonly-feedback branch from 6761296 to a7c8bcf Compare September 15, 2026 20:00
@kube
kube force-pushed the codex/fe-1660-readonly-feedback branch from a7c8bcf to ade6d39 Compare September 15, 2026 20:39
@kube
kube removed this pull request from stack #9732 October 9, 2026 02:33
@kube
kube force-pushed the codex/fe-1660-readonly-feedback branch from ade6d39 to 47f6f87 Compare October 9, 2026 02:34
@kube
kube requested a review from a team as a code owner October 9, 2026 02:34
@kube
kube added this pull request to stack #9974 October 9, 2026 02:34
kube added 2 commits October 9, 2026 22:04
A blocked node drag, editing shortcut, paste or delete shows one brief notice
saying why: the host made the net read-only, a mode other than Edit is open,
or a simulation holds the net. A host can add an action to the read-only
notice through readOnlyAction, carried with the other host-owned net actions;
published examples offer Make a local copy there.

Neutral notifications now render: Ark shows only its own toast types, so a
neutral tone maps to info.
Notifications live in a store shared by every editor on the page. The
unmount cleanup dismissed them, and a dismissal animates out through each
toast's own machine, which unmounts with the editor, so the next editor
showed the toast again. Make a local copy in the read-only notice left
"This document is read-only." on the editable copy. The cleanup now removes
them at once.

This branch was successfully deployed

3 active deployments
Preview – hash — d326e68c Deployed Oct 9, 2026 by vercel[bot]
Preview – petrinaut-docs — d326e68c Deployed Oct 9, 2026 by vercel[bot]
Preview – petrinaut — d326e68c Deployed Oct 9, 2026 by vercel[bot]
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