Skip to content

feat: Guided Tours Framework (Secrets)#2405

Draft
camielvs wants to merge 2 commits into
06-03-feat_guided_tour_-_subgraphsfrom
06-10-feat_guided_tours_framework_secrets_
Draft

feat: Guided Tours Framework (Secrets)#2405
camielvs wants to merge 2 commits into
06-03-feat_guided_tour_-_subgraphsfrom
06-10-feat_guided_tours_framework_secrets_

Conversation

@camielvs

@camielvs camielvs commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Description

The secret-specific interaction mechanics for the guided-tour framework, layered on the framework stack (#2348 / #2299 / #2347 / #2340) and the subgraphs mechanics (#2365). Foundation for the Using Secrets tour (#2406) — this PR adds the interaction types and bridge logic that detect them, the in-editor Settings → Secrets stand-in the tour opens, an in-memory mock backend so the secret steps stay hands-on without a real backend, and small reusability/behavior tweaks that let it all run without leaving the tour page. The tour content and DOM anchors land in #2406.

What changed

Interaction vocabulary (src/components/Learn/tours/registry.ts)

Five new TourStep.interaction values, plus a tourPanel field, plus a tour-level mockBackend flag (see below):

  • assign-secret-argument — a task argument's value becomes a secret (MobX activeSpec reaction via isSecretArgument; optionally gated to a targetArgumentName)
  • assign-secret-submit — a secret gets bound inside the submit dialog. The value lives in the dialog's local React state (not the spec), so this is detected from the DOM rather than a spec reaction
  • open-secret-dialog / open-settings-panel / open-submit-dialog — the respective dialog appears in the DOM
  • tourPanel: "secrets-manager" — marks the steps during which the in-editor Settings stand-in should be open

Bridge handlers (src/routes/v2/pages/Editor/components/EditorTourBridge.tsx)

Each interaction marks the step complete in the shared tour-progress state (following #2299; it doesn't advance the tour itself). The three open-* handlers are MutationObserver DOM-presence checks; assign-secret-argument is a spec reaction; assign-secret-submit watches for the secret display inside the submit dialog. Already-satisfied-on-entry states are marked complete immediately; gated "Next" / auto-advance (#2340) handle progression.

Checklist labels (src/providers/TourProvider/tourActionLabels.ts + test)

Copy for the five interactions, e.g. assign-secret-argument → "Assign a secret to the {targetArgumentName} argument", open-settings-panel → "Open Settings to manage your secrets".

In-editor Settings → Secrets stand-in (TourSecretsDialog.tsx, new)

Navigating to the real /settings/secrets route would unmount the tour page and tear the tour down. Instead, a non-modal dialog mirrors the real settings shell (sidebar with Secrets active, the other tabs disabled) and renders the real SecretsListView, keeping add/replace in-dialog rather than using the Settings router links. It opens when the active step is marked tourPanel: "secrets-manager" and the user clicks the gear (openTourSettings), and closes when the tour leaves those steps.

  • AppMenuActions.tsx — in tour mode the Settings gear calls openTourSettings() instead of routing away (keeps its data-tracking-id so the tour can anchor to it).
  • EditorV2.tsx — mounts <TourSecretsDialog /> alongside the existing tour dialogs.

No-backend mock backend (tourMockBackend.ts new, secretsStorage.ts, Tour.tsx, secret/submit gates)

Secrets live on the backend, so without one the secret steps would otherwise trap the user on a step they can't complete. When a tour opts in (TourDefinition.mockBackend) and there's no real backend, the secrets backend is mocked in-memory so the steps stay fully hands-on — the user really opens the picker, adds a secret, picks it, and assigns it, against an ephemeral store that is cleared when the tour ends. Nothing is persisted or sent anywhere; with a real backend this is inert.

  • tourMockBackend.ts (new) — a provider-free module store: setTourMockActive/isTourMockActive, a useTourMockBackend() hook, and an in-memory Secret map (mockListSecrets/mockAddSecret/mockUpdateSecret/mockRemoveSecret).
  • secretsStorage.tsfetchSecretsList/addSecret/updateSecret/removeSecret route to the in-memory store when the mock is active (the existing SecretsQueryKeys.All() invalidations keep the list fresh).
  • Tour.tsx — a TourMockBackendController activates the mock while tour.mockBackend && !available and clears it (and the store) on tour exit.
  • Gates accept the mock: SelectSecretDialog / SecretsList render the real picker (available || mock); the run-with-arguments (split-arrows) button enables so the submit dialog can open. The primary Submit button and the submit-args confirm stay gated on real availability — the secret-to-input assignment is demonstrated, but launching a real run isn't wired in mock mode.

Friendly no-backend empty state (SecretsBackendUnavailable.tsx, new)

SelectSecretDialog / SecretsList show a "Backend not connected" state (Lock/DB icon + copy) instead of the generic error-boundary icon when there's genuinely no backend and the mock isn't active — which also improves the real Settings → Secrets page for backend-less setups.

Reusable secrets components (SecretsList.tsx, SecretsListView.tsx)

Optional onAddSecret / onEditSecret callbacks. They default to the existing router links (real Settings page is unchanged), but let the stand-in reuse the real list/forms with in-dialog add/replace — so the tour isn't a hand-maintained copy of the secrets UI.

Popover & dialog behavior

  • TourPopover.tsxcomputeDefaultPopoverPosition gains a branch for a tall, centered modal: anchor the popover to its left, aligned to the dialog's top edge (rather than vertically centered).
  • SubmitTaskArgumentsDialog.tsx — renders modal={!tourMode}; non-modal during a tour so the portaled tour popover (Next / Finish Tour) stays clickable while the dialog is open. Behavior outside tours is unchanged.

Related Issue and Pull requests

Progresses https://github.com/Shopify/oasis-frontend/issues/583

Builds on the framework stack (#2348 / #2299 / #2347 / #2340 / #2365); consumed by the Using Secrets tour in #2406.

Type of Change

  • New feature

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Test Instructions

The registry is otherwise inert in this PR — the interactions are exercised end-to-end by the Using Secrets tour in #2406. To verify in isolation:

  • No regressions in the existing tours and in the real Settings → Secrets page (add / replace / delete still navigate and work as before).
  • No backend: the Using Secrets tour (feat: Guided Tour - Secrets #2406) runs fully hands-on against the in-memory mock — the secret picker/list show real content (not the error icon), steps gate normally, and no /api/secrets calls fire. Settings → Secrets with no backend shows the "Backend not connected" state.
  • With a backend: behavior is unchanged (real secrets, real submit).
  • Submit dialog outside a tour is still modal (focus trap + scrim) as before.
  • pnpm typecheck, pnpm lint, and the tourActionLabels / tourMockBackend unit tests pass.

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: 06-10-feat_guided_tours_framework_secrets_/a386028

camielvs commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator Author

@camielvs camielvs added the #gsd:50583 Learning Hub label Jun 10, 2026 — with Graphite App
@camielvs camielvs force-pushed the 06-10-feat_guided_tours_framework_secrets_ branch 2 times, most recently from 62653bf to d7a841f Compare June 11, 2026 20:32
@camielvs camielvs force-pushed the 06-03-feat_guided_tour_-_subgraphs branch from f541439 to 4b15ecd Compare June 11, 2026 20:32
@camielvs camielvs force-pushed the 06-10-feat_guided_tours_framework_secrets_ branch from d7a841f to c7356f5 Compare June 11, 2026 20:55
When a tour opts in (TourDefinition.mockBackend) and runs without a real
backend, mock the secrets backend in-memory so its secret steps stay hands-on
(open the picker, add/pick/assign a secret) against an ephemeral store cleared
when the tour ends. Steps gate normally; the submit dialog opens to demonstrate
assigning a secret to a run input, but real run submission stays gated on
availability.

- tourMockBackend: module store + useTourMockBackend hook + in-memory secrets
- secretsStorage routes to the mock when active
- TourMockBackendController activates it (tour.mockBackend && !available)
- secrets list/picker + run-with-arguments button accept the mock; submit
  confirm stays disabled in mock mode
- Replaces the earlier read-only degrade (drops requiresBackend gating
  relaxation, fallbackContent/BackendAwareStepContent); keeps the
  SecretsBackendUnavailable empty state for non-tour Settings -> Secrets

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@camielvs camielvs mentioned this pull request Jun 13, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

#gsd:50583 Learning Hub

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant