Skip to content

feat(code): inbox onboarding takeover + Agents callout#2567

Open
Twixes wants to merge 2 commits into
mainfrom
inbox-onboarding
Open

feat(code): inbox onboarding takeover + Agents callout#2567
Twixes wants to merge 2 commits into
mainfrom
inbox-onboarding

Conversation

@Twixes

@Twixes Twixes commented Jun 10, 2026

Copy link
Copy Markdown
Member

Stacked on top of #2547 (Inbox 2.0).

Summary

Adds the inbox onboarding flow that was pulled out of the Inbox 2.0 PR to keep the review surfaces cleanly separated.

  • Welcome scene — full-screen takeover when integrations aren't set up. Hero leads with "Self-driving for your product." Three-beat story arc (PR → Slack delivery → @PostHog mention) with high-fidelity preview clones of the actual production surfaces (PullRequestCard + Slack chrome with channel header, avatars, APP badge, @-mention pill, rich attachment).
  • Stepper takeover — strictly linear: Slack → GitHub → Sources → Notifications. Slack offers a session-scoped "I don't use Slack — skip" exit; the rest gate-and-go. Each step has a journey eyebrow (Step 2 of 4 · Self-driving setup) and a per-step hedgehog tip below the action card.
  • Agents callout — slim sticky strip above the config when the inbox isn't done yet. Links back to the takeover.
  • State plumbinguseInboxOnboardingState derives per-step done-status from existing integration / team-config / source-toggle hooks. The GitHub gate uses the same useRepositoryIntegration signal the Agents view consumes ("Connected and active (N repos)") so the two surfaces agree. Session store carries slackSkipped + welcomeAcknowledged.

Test plan

  • Open the inbox with no integrations connected — welcome scene appears with three beats.
  • Click "Set it up" — stepper opens on Slack step with hog tip below.
  • Click "I don't use Slack — skip for now" — moves to GitHub; Notifications step disappears from the stepper.
  • Connect Slack, GitHub (with default repo), enable a source, pick a notification channel — inbox unlocks to the regular tabs.
  • Navigate to Agents while onboarding incomplete — slim "Finish setting up your inbox · N of M done · Continue →" callout shows above the config.
  • Welcome scene rebuilt to lead with "Self-driving for your product" and PR-first story arc — verify Slack DM chrome looks like Slack (not a stylised mock).

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

React Doctor found 7 issues in 2 files · 7 warnings.

7 warnings

src/features/inbox/components/onboarding/FakeSlack.tsx

src/features/inbox/components/onboarding/InboxOnboardingWelcome.tsx

Reviewed by React Doctor for commit 5ed440c.

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/code/src/renderer/features/inbox/components/onboarding/useInboxOnboardingState.ts:63-77
`isLoading` only covers `teamConfigLoading || sourcesLoading`, but `useIntegrationSelectors` reads from a zustand store that starts empty (`integrations: []`) and is populated asynchronously by `useIntegrations()`. Until that fetch resolves, `hasSlackIntegration` and `hasGithubIntegration` are both `false`, so `isComplete` computes as `false` before any integrations have loaded. Meanwhile, `isLoading` is already `false` if team-config and sources fetches finished first, meaning `showOnboarding = true` in `InboxView` and the welcome takeover flashes for fully-onboarded users on every page load. `useRepositoryIntegration` already exposes `isLoadingRepos` (= `integrationsPending || reposPending`) — including it covers both the integration-list and repos loading windows.

```suggestion
  const {
    hasGithubIntegration,
    repositories,
    isLoadingRepos,
  } = useRepositoryIntegration();
  const { data: teamConfig, isLoading: teamConfigLoading } =
    useSignalTeamConfig();
  const { displayValues, isLoading: sourcesLoading } = useSignalSourceToggles();
  const slackSkipped = useInboxOnboardingSessionStore((s) => s.slackSkipped);

  const slackDone = hasSlackIntegration || slackSkipped;
  const githubDone = hasGithubIntegration && repositories.length > 0;
  const sourcesDone = Object.values(displayValues).some(Boolean);
  const notificationsApplicable = hasSlackIntegration && !slackSkipped;
  const notificationsDone =
    !notificationsApplicable ||
    !!teamConfig?.default_slack_notification_channel;

  const isLoading = teamConfigLoading || sourcesLoading || isLoadingRepos;
```

Reviews (1): Last reviewed commit: "fix(code): onboarding welcome – PR-first..." | Re-trigger Greptile

Comment on lines +63 to +77
const { hasGithubIntegration, repositories } = useRepositoryIntegration();
const { data: teamConfig, isLoading: teamConfigLoading } =
useSignalTeamConfig();
const { displayValues, isLoading: sourcesLoading } = useSignalSourceToggles();
const slackSkipped = useInboxOnboardingSessionStore((s) => s.slackSkipped);

const slackDone = hasSlackIntegration || slackSkipped;
const githubDone = hasGithubIntegration && repositories.length > 0;
const sourcesDone = Object.values(displayValues).some(Boolean);
const notificationsApplicable = hasSlackIntegration && !slackSkipped;
const notificationsDone =
!notificationsApplicable ||
!!teamConfig?.default_slack_notification_channel;

const isLoading = teamConfigLoading || sourcesLoading;

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.

P1 isLoading only covers teamConfigLoading || sourcesLoading, but useIntegrationSelectors reads from a zustand store that starts empty (integrations: []) and is populated asynchronously by useIntegrations(). Until that fetch resolves, hasSlackIntegration and hasGithubIntegration are both false, so isComplete computes as false before any integrations have loaded. Meanwhile, isLoading is already false if team-config and sources fetches finished first, meaning showOnboarding = true in InboxView and the welcome takeover flashes for fully-onboarded users on every page load. useRepositoryIntegration already exposes isLoadingRepos (= integrationsPending || reposPending) — including it covers both the integration-list and repos loading windows.

Suggested change
const { hasGithubIntegration, repositories } = useRepositoryIntegration();
const { data: teamConfig, isLoading: teamConfigLoading } =
useSignalTeamConfig();
const { displayValues, isLoading: sourcesLoading } = useSignalSourceToggles();
const slackSkipped = useInboxOnboardingSessionStore((s) => s.slackSkipped);
const slackDone = hasSlackIntegration || slackSkipped;
const githubDone = hasGithubIntegration && repositories.length > 0;
const sourcesDone = Object.values(displayValues).some(Boolean);
const notificationsApplicable = hasSlackIntegration && !slackSkipped;
const notificationsDone =
!notificationsApplicable ||
!!teamConfig?.default_slack_notification_channel;
const isLoading = teamConfigLoading || sourcesLoading;
const {
hasGithubIntegration,
repositories,
isLoadingRepos,
} = useRepositoryIntegration();
const { data: teamConfig, isLoading: teamConfigLoading } =
useSignalTeamConfig();
const { displayValues, isLoading: sourcesLoading } = useSignalSourceToggles();
const slackSkipped = useInboxOnboardingSessionStore((s) => s.slackSkipped);
const slackDone = hasSlackIntegration || slackSkipped;
const githubDone = hasGithubIntegration && repositories.length > 0;
const sourcesDone = Object.values(displayValues).some(Boolean);
const notificationsApplicable = hasSlackIntegration && !slackSkipped;
const notificationsDone =
!notificationsApplicable ||
!!teamConfig?.default_slack_notification_channel;
const isLoading = teamConfigLoading || sourcesLoading || isLoadingRepos;
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/inbox/components/onboarding/useInboxOnboardingState.ts
Line: 63-77

Comment:
`isLoading` only covers `teamConfigLoading || sourcesLoading`, but `useIntegrationSelectors` reads from a zustand store that starts empty (`integrations: []`) and is populated asynchronously by `useIntegrations()`. Until that fetch resolves, `hasSlackIntegration` and `hasGithubIntegration` are both `false`, so `isComplete` computes as `false` before any integrations have loaded. Meanwhile, `isLoading` is already `false` if team-config and sources fetches finished first, meaning `showOnboarding = true` in `InboxView` and the welcome takeover flashes for fully-onboarded users on every page load. `useRepositoryIntegration` already exposes `isLoadingRepos` (= `integrationsPending || reposPending`) — including it covers both the integration-list and repos loading windows.

```suggestion
  const {
    hasGithubIntegration,
    repositories,
    isLoadingRepos,
  } = useRepositoryIntegration();
  const { data: teamConfig, isLoading: teamConfigLoading } =
    useSignalTeamConfig();
  const { displayValues, isLoading: sourcesLoading } = useSignalSourceToggles();
  const slackSkipped = useInboxOnboardingSessionStore((s) => s.slackSkipped);

  const slackDone = hasSlackIntegration || slackSkipped;
  const githubDone = hasGithubIntegration && repositories.length > 0;
  const sourcesDone = Object.values(displayValues).some(Boolean);
  const notificationsApplicable = hasSlackIntegration && !slackSkipped;
  const notificationsDone =
    !notificationsApplicable ||
    !!teamConfig?.default_slack_notification_channel;

  const isLoading = teamConfigLoading || sourcesLoading || isLoadingRepos;
```

How can I resolve this? If you propose a fix, please make it concise.

Twixes commented Jun 10, 2026

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Twixes Twixes mentioned this pull request Jun 10, 2026
@Twixes Twixes force-pushed the inbox-onboarding branch from adc4b62 to bca04d4 Compare June 10, 2026 08:55
@Twixes Twixes changed the base branch from inbox-v2-pr to graphite-base/2567 June 10, 2026 09:00
@Twixes Twixes force-pushed the inbox-onboarding branch from bca04d4 to c8d2cb1 Compare June 10, 2026 09:00
@Twixes Twixes changed the base branch from graphite-base/2567 to inbox-v2-pr June 10, 2026 09:01
@Twixes Twixes force-pushed the inbox-onboarding branch from c8d2cb1 to 5d888ae Compare June 10, 2026 09:05
@Twixes Twixes force-pushed the inbox-onboarding branch from 5d888ae to 8ad85c7 Compare June 10, 2026 09:07
@Twixes Twixes force-pushed the inbox-onboarding branch from 8ad85c7 to 60a9c02 Compare June 10, 2026 09:08
@Twixes Twixes force-pushed the inbox-onboarding branch from 60a9c02 to 482ba4a Compare June 10, 2026 10:12
@Twixes Twixes force-pushed the inbox-onboarding branch from 482ba4a to b9dbe98 Compare June 10, 2026 10:14
@Twixes Twixes changed the base branch from inbox-v2-pr to graphite-base/2567 June 10, 2026 10:21
@Twixes Twixes force-pushed the graphite-base/2567 branch from 6b2e984 to ee7e31d Compare June 10, 2026 10:22
@Twixes Twixes force-pushed the inbox-onboarding branch from b9dbe98 to fc873c7 Compare June 10, 2026 10:22
@Twixes Twixes changed the base branch from graphite-base/2567 to inbox-v2-pr June 10, 2026 10:22
@Twixes Twixes force-pushed the inbox-onboarding branch 2 times, most recently from 593e8ba to 76381e4 Compare June 10, 2026 11:11
@Twixes Twixes force-pushed the inbox-onboarding branch from 76381e4 to a48efe0 Compare June 10, 2026 11:31
@Twixes Twixes force-pushed the inbox-onboarding branch from a48efe0 to 057dd91 Compare June 10, 2026 11:48
@Twixes Twixes changed the base branch from inbox-v2-pr to graphite-base/2567 June 10, 2026 11:58
@Twixes Twixes force-pushed the graphite-base/2567 branch from d31c1b2 to 8031116 Compare June 10, 2026 11:58
@Twixes Twixes force-pushed the inbox-onboarding branch from 057dd91 to ad98f6a Compare June 10, 2026 12:04
@Twixes Twixes changed the base branch from graphite-base/2567 to main June 10, 2026 12:04
@Twixes Twixes force-pushed the inbox-onboarding branch 3 times, most recently from c254873 to 6066d0b Compare June 10, 2026 12:17
Twixes added 2 commits June 11, 2026 10:25
Rework the inbox onboarding into a sleeker, navigable stepper:
Welcome -> Connect GitHub -> Connect Slack -> Activate agents, with an
explicit cursor so the user can move backward as well as forward.

- Welcome is now the first step (content extracted to InboxWelcomeContent);
  the pane owns Back/Continue, gated on each step being satisfied.
- Activate step bundles signal sources + the default Slack channel; the
  primary CTA becomes "Activate agents". A session latch decouples
  visibility from isComplete so finishing the last step doesn't yank the
  pane mid-flow.
- Welcome previews: extract a presentational PullRequestCardView reused by
  the real PullRequestCard, plus a high-fidelity FakeSlack component set
  (real report-notification block layout, PostHog Slack-app avatar,
  app-scaled text, Slack-style button hover/active, meep sound effects,
  Silicon Valley characters).
- Fix broken Radix decimal gap tokens (gap="2.5" etc.) by switching to
  Tailwind gap utilities.
@Twixes Twixes force-pushed the inbox-onboarding branch from 6066d0b to 5ed440c Compare June 11, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant