Show onboarding banner to link to YT video & do not show release note on first-time (#1490)

<!-- This is an auto-generated description by cubic. -->

## Summary by cubic
Adds an onboarding banner in Setup that links to a 3-minute YouTube
intro and dismisses after click. Also avoids showing release notes on a
user’s first launch.

- **New Features**
- Added OnboardingBanner component with YouTube thumbnail and play icon.
  - Opens the video via IpcClient and hides the banner after click.
  - Integrated into SetupBanner with local visibility state.

- **Bug Fixes**
  - Don’t show release notes on first run to prevent spam.

<!-- End of auto-generated description by cubic. -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a dismissible onboarding banner linking to a YouTube intro and
changes release notes to appear only on app updates, not first run.
> 
> - **UI/Onboarding**:
> - **`src/components/home/OnboardingBanner.tsx`**: New banner component
with YouTube thumbnail/play icon; opens intro video via
`IpcClient.openExternalUrl`; hides itself on click.
> - **`src/components/SetupBanner.tsx`**: Integrates `OnboardingBanner`
with `isOnboardingVisible` state; tweaks header typography
(`font-medium`).
> - **Release Notes Behavior**:
> - **`src/pages/home.tsx`**: Only shows release notes when upgrading
(checks existing `settings.lastShownReleaseNotesVersion` before opening
modal); preserves themed URL handling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
832e70f87b3b6a7e8b8b921fe8c6ceb15198cce0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This commit is contained in:
Will Chen
2025-10-09 13:27:16 -07:00
committed by GitHub
parent 83126a7e65
commit 916d6fdb63
3 changed files with 71 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ import { useLanguageModelProviders } from "@/hooks/useLanguageModelProviders";
import { useScrollAndNavigateTo } from "@/hooks/useScrollAndNavigateTo";
// @ts-ignore
import logo from "../../assets/logo.svg";
import { OnboardingBanner } from "./home/OnboardingBanner";
type NodeInstallStep =
| "install"
@@ -40,6 +41,7 @@ type NodeInstallStep =
export function SetupBanner() {
const posthog = usePostHog();
const navigate = useNavigate();
const [isOnboardingVisible, setIsOnboardingVisible] = useState(true);
const { isAnyProviderSetup, isLoading: loading } =
useLanguageModelProviders();
const [nodeSystemInfo, setNodeSystemInfo] = useState<NodeSystemInfo | null>(
@@ -147,7 +149,13 @@ export function SetupBanner() {
return (
<>
<p className="text-xl text-zinc-700 dark:text-zinc-300 p-4">Setup Dyad</p>
<p className="text-xl font-medium text-zinc-700 dark:text-zinc-300 p-4">
Setup Dyad
</p>
<OnboardingBanner
isVisible={isOnboardingVisible}
setIsVisible={setIsOnboardingVisible}
/>
<div className={bannerClasses}>
<Accordion
type="multiple"

View File

@@ -0,0 +1,56 @@
import { IpcClient } from "@/ipc/ipc_client";
import { Play } from "lucide-react";
export const OnboardingBanner = ({
isVisible,
setIsVisible,
}: {
isVisible: boolean;
setIsVisible: (isVisible: boolean) => void;
}) => {
if (!isVisible) return null;
return (
// <div className="fixed top-0 left-0 right-0 z-50 flex justify-center mt-2">
<div className="max-w-xl w-full mx-4 relative mb-4">
<a
onClick={(e) => {
e.preventDefault();
IpcClient.getInstance().openExternalUrl(
"https://www.youtube.com/watch?v=rgdNoHLaRN4",
);
setIsVisible(false);
}}
target="_blank"
rel="noopener noreferrer"
className="cursor-pointer block bg-(--background-lightest) border border-border rounded-lg shadow-lg hover:bg-accent transition-colors"
>
<div className="flex items-center">
<div className="relative p-2">
<img
src="https://img.youtube.com/vi/rgdNoHLaRN4/maxresdefault.jpg"
alt="Get started with Dyad in 3 minutes"
className="w-28 h-16 object-cover rounded-md"
/>
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-10 h-10 bg-background rounded-full flex items-center justify-center shadow-md">
<Play size={20} className="text-foreground ml-0.5" />
</div>
</div>
</div>
<div className="flex-1 px-4 py-3">
<div className="text-foreground">
<p className="font-semibold text-base">
Get started with Dyad in 3 minutes
</p>
<p className="text-sm text-muted-foreground">
Start building your app for free
</p>
</div>
</div>
</div>
</a>
</div>
// </div>
);
};

View File

@@ -62,9 +62,15 @@ export default function HomePage() {
settings &&
settings.lastShownReleaseNotesVersion !== appVersion
) {
const shouldShowReleaseNotes = !!settings.lastShownReleaseNotesVersion;
await updateSettings({
lastShownReleaseNotesVersion: appVersion,
});
// It feels spammy to show release notes if it's
// the users very first time.
if (!shouldShowReleaseNotes) {
return;
}
try {
const result = await IpcClient.getInstance().doesReleaseNoteExist({