diff --git a/.changeset/wet-hands-roll.md b/.changeset/wet-hands-roll.md
new file mode 100644
index 0000000000..96c6652b3d
--- /dev/null
+++ b/.changeset/wet-hands-roll.md
@@ -0,0 +1,5 @@
+---
+'posthog-js': patch
+---
+
+add animation option for tour banners
diff --git a/packages/browser/src/extensions/product-tours/components/ProductTourBanner.tsx b/packages/browser/src/extensions/product-tours/components/ProductTourBanner.tsx
index 50c7a3f14a..5b9b2c2d45 100644
--- a/packages/browser/src/extensions/product-tours/components/ProductTourBanner.tsx
+++ b/packages/browser/src/extensions/product-tours/components/ProductTourBanner.tsx
@@ -56,7 +56,17 @@ function StaticWrapper({ class: className, children }: BannerWrapperProps): h.JS
return
{children}
}
-export function ProductTourBanner({
+export function ProductTourBanner(props: ProductTourBannerProps) {
+ return (
+
+ )
+}
+
+function ProductTourBannerInner({
step,
onDismiss,
onActionClick,
diff --git a/packages/browser/src/extensions/product-tours/product-tour.css b/packages/browser/src/extensions/product-tours/product-tour.css
index 97048e1859..49b401ade8 100644
--- a/packages/browser/src/extensions/product-tours/product-tour.css
+++ b/packages/browser/src/extensions/product-tours/product-tour.css
@@ -560,6 +560,25 @@
}
/* Banner styles */
+@keyframes ph-tour-banner-slide-in {
+ from {
+ grid-template-rows: 0fr;
+ }
+ to {
+ grid-template-rows: 1fr;
+ }
+}
+
+.ph-tour-banner-wrapper {
+ display: grid;
+ animation: ph-tour-banner-slide-in var(--ph-tour-banner-animation-duration, 300ms) ease-out forwards;
+}
+
+.ph-tour-banner-slide {
+ overflow: hidden;
+ min-height: 0;
+}
+
.ph-tour-banner {
display: flex;
align-items: center;
diff --git a/packages/browser/src/extensions/product-tours/product-tours.tsx b/packages/browser/src/extensions/product-tours/product-tours.tsx
index d8205976d9..b1b66106a0 100644
--- a/packages/browser/src/extensions/product-tours/product-tours.tsx
+++ b/packages/browser/src/extensions/product-tours/product-tours.tsx
@@ -30,7 +30,7 @@ import { createLogger } from '../../utils/logger'
import { document as _document, window as _window } from '../../utils/globals'
import { localStore, sessionStore } from '../../storage'
import { addEventListener } from '../../utils'
-import { isNull, SurveyMatchType } from '@posthog/core'
+import { isNull, isUndefined, SurveyMatchType } from '@posthog/core'
import { propertyComparisons } from '../../utils/property-utils'
import {
TOUR_SHOWN_KEY_PREFIX,
@@ -154,6 +154,10 @@ function retrieveBannerShadow(
addProductTourCSSVariablesToElement(div, tour.appearance)
+ if (!isUndefined(bannerConfig?.animation?.duration)) {
+ div.style.setProperty('--ph-tour-banner-animation-duration', `${bannerConfig.animation.duration}ms`)
+ }
+
const shadow = div.attachShadow({ mode: 'open' })
const stylesheet = getProductTourStylesheet()
diff --git a/packages/browser/src/posthog-product-tours-types.ts b/packages/browser/src/posthog-product-tours-types.ts
index 4973b65808..654dfdb9c5 100644
--- a/packages/browser/src/posthog-product-tours-types.ts
+++ b/packages/browser/src/posthog-product-tours-types.ts
@@ -22,6 +22,9 @@ export interface ProductTourBannerConfig {
link?: string
tourId?: string
}
+ animation?: {
+ duration?: number
+ }
}
/** Button actions available on modal steps */
diff --git a/playground/nextjs/pages/product-tours.tsx b/playground/nextjs/pages/product-tours.tsx
index 90a8801baf..d2f7cb1310 100644
--- a/playground/nextjs/pages/product-tours.tsx
+++ b/playground/nextjs/pages/product-tours.tsx
@@ -53,6 +53,8 @@ export default function ProductTours() {
return (
+
+
Product Tours Playground
{/* Tour Controls */}