Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
useGithubRepositories,
useRepositoryIntegration,
} from "@hooks/useIntegrations";
import { Box, Button, Flex, Text, TextField } from "@radix-ui/themes";
import { Button } from "@posthog/quill";
import { Box, Flex, Text, TextField } from "@radix-ui/themes";
import { trpcClient } from "@renderer/trpc";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "sonner";
Expand Down Expand Up @@ -185,11 +186,18 @@ function GitHubSetup({ onComplete, onCancel }: SetupFormProps) {
{statusMessage}
</Text>
<Flex gap="2" justify="end">
<Button size="2" variant="soft" onClick={onCancel}>
<Button
type="button"
variant="outline"
size="sm"
onClick={onCancel}
>
Cancel
</Button>
<Button
size="2"
type="button"
variant="primary"
size="sm"
onClick={() => void handleConnectGitHub()}
disabled={connecting}
>
Expand Down Expand Up @@ -228,11 +236,19 @@ function GitHubSetup({ onComplete, onCancel }: SetupFormProps) {
/>

<Flex gap="2" justify="end">
<Button size="2" variant="soft" onClick={onCancel} disabled={loading}>
<Button
type="button"
variant="outline"
size="sm"
onClick={onCancel}
disabled={loading}
>
Cancel
</Button>
<Button
size="2"
type="button"
variant="primary"
size="sm"
onClick={handleSubmit}
disabled={!repo || !selectedIntegrationId || loading}
>
Expand Down Expand Up @@ -345,8 +361,9 @@ function LinearSetup({ onComplete }: SetupFormProps) {
<SetupFormContainer title="Connect Linear">
<Flex direction="column" gap="3">
<Button
size="2"
variant="soft"
type="button"
variant="primary"
size="sm"
onClick={handleOAuthConnect}
disabled={loading || oauthConnected}
>
Expand All @@ -363,7 +380,9 @@ function LinearSetup({ onComplete }: SetupFormProps) {

<Flex gap="2" justify="end">
<Button
size="2"
type="button"
variant="primary"
size="sm"
onClick={handleSubmit}
disabled={!oauthConnected || loading}
>
Expand Down Expand Up @@ -436,11 +455,19 @@ function ZendeskSetup({ onComplete, onCancel }: SetupFormProps) {
/>

<Flex gap="2" justify="end">
<Button size="2" variant="soft" onClick={onCancel} disabled={loading}>
<Button
type="button"
variant="outline"
size="sm"
onClick={onCancel}
disabled={loading}
>
Cancel
</Button>
<Button
size="2"
type="button"
variant="primary"
size="sm"
onClick={handleSubmit}
disabled={!canSubmit || loading}
>
Expand Down Expand Up @@ -505,11 +532,19 @@ function PgAnalyzeSetup({ onComplete, onCancel }: SetupFormProps) {
/>

<Flex gap="2" justify="end">
<Button size="2" variant="soft" onClick={onCancel} disabled={loading}>
<Button
type="button"
variant="outline"
size="sm"
onClick={onCancel}
disabled={loading}
>
Cancel
</Button>
<Button
size="2"
type="button"
variant="primary"
size="sm"
onClick={handleSubmit}
disabled={!canSubmit || loading}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,78 +1,16 @@
import { AnimatedEllipsis } from "@features/inbox/components/utils/AnimatedEllipsis";
import { SOURCE_PRODUCT_META } from "@features/inbox/components/utils/source-product-icons";
import { ArrowDownIcon, CheckCircleIcon } from "@phosphor-icons/react";
import { CheckCircleIcon } from "@phosphor-icons/react";
import { Box, Button, Flex, Text, Tooltip } from "@radix-ui/themes";
import builderHog from "@renderer/assets/images/hedgehogs/builder-hog-03.png";
import explorerHog from "@renderer/assets/images/hedgehogs/explorer-hog.png";
import graphsHog from "@renderer/assets/images/hedgehogs/graphs-hog.png";
import mailHog from "@renderer/assets/images/mail-hog.png";
import { ANALYTICS_EVENTS } from "@shared/types/analytics";
import { track } from "@utils/analytics";
import { useState } from "react";

// ── Full-width empty states ─────────────────────────────────────────────────

export function WelcomePane({ onEnableInbox }: { onEnableInbox: () => void }) {
return (
<Flex
direction="column"
align="center"
justify="center"
height="100%"
px="5"
>
<Flex direction="column" align="center" className="max-w-[420px]">
<img src={graphsHog} alt="" className="mb-[16px] w-[120px]" />

<Text
align="center"
className="font-bold text-(--gray-12) text-lg leading-6.5"
>
Welcome to your Inbox
</Text>

<Flex
direction="column"
align="center"
gap="3"
mt="3"
className="max-w-[340px]"
>
<Text
align="center"
className="text-(--gray-11) text-[13px] leading-[1.35]"
>
<Text className="font-medium text-(--gray-12)">
Background analysis of your data — while you sleep.
</Text>
<br />
Session recordings watched automatically. Issues, tickets, and evals
analyzed around the clock.
</Text>

<ArrowDownIcon size={14} className="text-(--gray-8)" />

<Text
align="center"
className="text-(--gray-11) text-[13px] leading-[1.35]"
>
<Text className="font-medium text-(--gray-12)">
Ready-to-run fixes for real user problems.
</Text>
<br />
Each report includes evidence and impact numbers — just execute the
prompt in your agent.
</Text>
</Flex>

<Button size="2" onClick={onEnableInbox} className="mt-[20px]">
Enable Inbox
</Button>
</Flex>
</Flex>
);
}

export function WarmingUpPane({
onConfigureSources,
enabledProducts,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { SignalSourcesSettings } from "@features/settings/components/sections/SignalSourcesSettings";
import { ArrowRightIcon } from "@phosphor-icons/react";
import { Button } from "@posthog/quill";
import { Flex, Text, Tooltip } from "@radix-ui/themes";
import { motion } from "framer-motion";

interface InboxSetupPaneProps {
hasSignalSources: boolean;
onProceedToInbox: () => void;
}

export function InboxSetupPane({
hasSignalSources,
onProceedToInbox,
}: InboxSetupPaneProps) {
return (
<Flex align="center" justify="center" height="100%" width="100%" px="6">
<Flex
direction="column"
gap="2"
className="w-full max-w-[720px] py-[24px]"
>
<motion.div
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
>
<Text className="font-bold text-(--gray-12) text-2xl">
Set up self-driving for your product
</Text>
</motion.div>

<motion.div
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, delay: 0.05 }}
>
<SignalSourcesSettings />
</motion.div>

<Flex justify="end" mt="2">
{hasSignalSources ? (
<Button
type="button"
variant="primary"
size="sm"
onClick={onProceedToInbox}
>
Proceed to Inbox
<ArrowRightIcon size={14} />
</Button>
) : (
<Tooltip content="Enable at least one source first">
<span className="inline-flex cursor-not-allowed">
<Button type="button" variant="primary" size="sm" disabled>
Proceed to Inbox
<ArrowRightIcon size={14} />
</Button>
</span>
</Tooltip>
)}
</Flex>
</Flex>
</Flex>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
SelectReportPane,
SkeletonBackdrop,
WarmingUpPane,
WelcomePane,
} from "@features/inbox/components/InboxEmptyStates";
import { InboxSetupPane } from "@features/inbox/components/InboxSetupPane";
import { InboxSourcesDialog } from "@features/inbox/components/InboxSourcesDialog";
import {
inboxBulkSnoozeDisabledReason,
Expand Down Expand Up @@ -475,11 +475,25 @@ export function InboxSignalsTab() {
sourceProductFilter.length > 0 ||
suggestedReviewerFilter.length > 0 ||
statusFilter.length < 5;
// Onboarding wins over two-pane even if the user has suggested setup tasks —
// discovered tasks alone shouldn't push a source-less user past the inline setup.
const onboardingShouldShow = !hasReports && !hasSignalSources;
// Sticky within an inbox visit: once we've entered onboarding, keep showing
// it even after the user toggles a source on, until either they explicitly
// click "Proceed to Inbox" or navigate away (unmount resets the ref).
const enteredOnboardingRef = useRef(false);
if (onboardingShouldShow) {
enteredOnboardingRef.current = true;
}
const [userExitedOnboarding, setUserExitedOnboarding] = useState(false);
const showInboxOnboarding =
enteredOnboardingRef.current && !userExitedOnboarding;
const shouldShowTwoPane =
hasReports ||
!!searchQuery.trim() ||
hasActiveFilters ||
hasDiscoveredTasks;
!showInboxOnboarding &&
(hasReports ||
!!searchQuery.trim() ||
hasActiveFilters ||
hasDiscoveredTasks);

// Sticky: once we enter two-pane mode, stay there even if a refetch
// momentarily empties the list (e.g. when sort order changes).
Expand Down Expand Up @@ -686,7 +700,19 @@ export function InboxSignalsTab() {

return (
<>
{showTwoPaneLayout ? (
{showInboxOnboarding ? (
// Inline setup pane for users with no sources configured.
// The toolbar (report counter, search, bulk actions) is suppressed
// entirely — none of it is meaningful before any source is configured.
// Sticky within the visit: stays until the user clicks "Proceed to
// Inbox" inside the pane or navigates away.
<ScrollArea className="h-full">
<InboxSetupPane
hasSignalSources={hasSignalSources}
onProceedToInbox={() => setUserExitedOnboarding(true)}
/>
</ScrollArea>
) : showTwoPaneLayout ? (
<Flex ref={containerRef} height="100%" className="min-h-0">
{/* ── Left pane: report list ───────────────────────────────── */}
<Box
Expand Down Expand Up @@ -831,7 +857,7 @@ export function InboxSignalsTab() {
</Flex>
</Flex>
) : (
/* ── Full-width empty state with skeleton backdrop ──────── */
// Full-width warming-up state with skeleton backdrop
<Box className="relative h-full">
<Flex direction="column">
<SignalsToolbar
Expand All @@ -853,14 +879,10 @@ export function InboxSignalsTab() {
className="pointer-events-none absolute inset-0 flex items-center justify-center"
>
<Box className="pointer-events-auto">
{!hasSignalSources || !hasGithubIntegration ? (
<WelcomePane onEnableInbox={() => setSourcesDialogOpen(true)} />
) : (
<WarmingUpPane
onConfigureSources={() => setSourcesDialogOpen(true)}
enabledProducts={enabledProducts}
/>
)}
<WarmingUpPane
onConfigureSources={() => setSourcesDialogOpen(true)}
enabledProducts={enabledProducts}
/>
</Box>
</Box>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@ import {
TicketIcon,
VideoIcon,
} from "@phosphor-icons/react";
import {
Box,
Button,
Flex,
Spinner,
Switch,
Text,
Tooltip,
} from "@radix-ui/themes";
import { Button } from "@posthog/quill";
import { Box, Flex, Spinner, Switch, Text, Tooltip } from "@radix-ui/themes";
import type { SignalSourceConfig } from "@renderer/api/posthogClient";
import { memo, useCallback } from "react";

Expand Down Expand Up @@ -140,7 +133,9 @@ const SignalSourceToggleCard = memo(function SignalSourceToggleCard({
<Spinner size="2" />
) : requiresSetup ? (
<Button
size="1"
type="button"
variant="primary"
size="sm"
onClick={(e) => {
e.stopPropagation();
onSetup?.();
Expand Down Expand Up @@ -215,7 +210,9 @@ export const EvaluationsSection = memo(function EvaluationsSection({
</Flex>
</Flex>
<Button
size="1"
type="button"
variant="primary"
size="sm"
onClick={(e) => {
e.stopPropagation();
window.open(evaluationsUrl, "_blank", "noopener");
Expand Down
Loading
Loading