Add sticky top sponsor

feat/sponsors
Kamran Ahmed 1 month ago
parent 2eb360a833
commit b062f01d18
  1. 8
      src/components/FrameRenderer/renderer.ts
  2. 9
      src/components/OnboardingNudge.tsx
  3. 2
      src/components/PageSponsors/BottomRightSponsor.tsx
  4. 20
      src/components/PageSponsors/PageSponsors.tsx
  5. 36
      src/components/PageSponsors/StickyTopSponsor.tsx
  6. 2
      src/stores/page.ts

@ -57,7 +57,7 @@ export class Renderer {
} }
// Clone it so we can use it later // Clone it so we can use it later
this.loaderHTML = this.loaderEl!.innerHTML; this.loaderHTML = this.loaderEl?.innerHTML!;
const dataset = this.containerEl.dataset; const dataset = this.containerEl.dataset;
this.resourceType = dataset.resourceType!; this.resourceType = dataset.resourceType!;
@ -66,11 +66,7 @@ export class Renderer {
return true; return true;
} }
/** jsonToSvg(jsonUrl: string): Promise<void> | null {
* @param { string } jsonUrl
* @returns {Promise<SVGElement>}
*/
jsonToSvg(jsonUrl: string) {
if (!jsonUrl) { if (!jsonUrl) {
console.error('jsonUrl not defined in frontmatter'); console.error('jsonUrl not defined in frontmatter');
return null; return null;

@ -2,6 +2,8 @@ import { cn } from '../lib/classname.ts';
import { memo, useEffect, useState } from 'react'; import { memo, useEffect, useState } from 'react';
import { useScrollPosition } from '../hooks/use-scroll-position.ts'; import { useScrollPosition } from '../hooks/use-scroll-position.ts';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import { isOnboardingStripHidden } from '../stores/page.ts';
import { useStore } from '@nanostores/react';
type OnboardingNudgeProps = { type OnboardingNudgeProps = {
onStartOnboarding: () => void; onStartOnboarding: () => void;
@ -14,6 +16,7 @@ export function OnboardingNudge(props: OnboardingNudgeProps) {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const $isOnboardingStripHidden = useStore(isOnboardingStripHidden);
const { y: scrollY } = useScrollPosition(); const { y: scrollY } = useScrollPosition();
useEffect(() => { useEffect(() => {
@ -30,10 +33,14 @@ export function OnboardingNudge(props: OnboardingNudgeProps) {
return null; return null;
} }
if ($isOnboardingStripHidden) {
return null;
}
return ( return (
<div <div
className={cn( className={cn(
'fixed left-0 right-0 top-0 z-[91] flex w-full items-center justify-center bg-yellow-300 border-b border-b-yellow-500/30 pt-1.5 pb-2', 'fixed left-0 right-0 top-0 z-[91] flex w-full items-center justify-center border-b border-b-yellow-500/30 bg-yellow-300 pb-2 pt-1.5',
{ {
'striped-loader': isLoading, 'striped-loader': isLoading,
}, },

@ -68,6 +68,8 @@ export function BottomRightSponsor(props: BottomRightSponsorProps) {
aria-label="Close" aria-label="Close"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation();
setIsHidden(true); setIsHidden(true);
onSponsorHidden(); onSponsorHidden();
}} }}

@ -2,7 +2,6 @@ import { useEffect, useState } from 'react';
import { httpGet, httpPatch } from '../../lib/http'; import { httpGet, httpPatch } from '../../lib/http';
import { sponsorHidden } from '../../stores/page'; import { sponsorHidden } from '../../stores/page';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { X } from 'lucide-react';
import { setViewSponsorCookie } from '../../lib/jwt'; import { setViewSponsorCookie } from '../../lib/jwt';
import { isMobile } from '../../lib/is-mobile'; import { isMobile } from '../../lib/is-mobile';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
@ -21,12 +20,21 @@ type PageSponsorType = {
id: string; id: string;
}; };
export type StickyTopSponsorType = PageSponsorType & {}; export type StickyTopSponsorType = PageSponsorType & {
buttonText: string;
style?: {
fromColor?: string;
toColor?: string;
textColor?: string;
buttonBackgroundColor?: string;
buttonTextColor?: string;
};
};
export type BottomRightSponsorType = PageSponsorType; export type BottomRightSponsorType = PageSponsorType;
type V1GetSponsorResponse = { type V1GetSponsorResponse = {
bottomRightAd?: PageSponsorType; bottomRightAd?: BottomRightSponsorType;
stickyTopAd?: PageSponsorType; stickyTopAd?: StickyTopSponsorType;
}; };
type PageSponsorsProps = { type PageSponsorsProps = {
@ -55,9 +63,9 @@ export function PageSponsors(props: PageSponsorsProps) {
const $isSponsorHidden = useStore(sponsorHidden); const $isSponsorHidden = useStore(sponsorHidden);
const [stickyTopSponsor, setStickyTopSponsor] = const [stickyTopSponsor, setStickyTopSponsor] =
useState<StickyTopSponsorType>(); useState<StickyTopSponsorType | null>();
const [bottomRightSponsor, setBottomRightSponsor] = const [bottomRightSponsor, setBottomRightSponsor] =
useState<BottomRightSponsorType>(); useState<BottomRightSponsorType | null>();
useEffect(() => { useEffect(() => {
const foundUtmParams = getUrlUtmParams(); const foundUtmParams = getUrlUtmParams();

@ -3,6 +3,7 @@ import { useScrollPosition } from '../../hooks/use-scroll-position.ts';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import type { StickyTopSponsorType } from './PageSponsors.tsx'; import type { StickyTopSponsorType } from './PageSponsors.tsx';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { isOnboardingStripHidden } from '../../stores/page.ts';
type StickyTopSponsorProps = { type StickyTopSponsorProps = {
sponsor: StickyTopSponsorType; sponsor: StickyTopSponsorType;
@ -22,6 +23,15 @@ export function StickyTopSponsor(props: StickyTopSponsorProps) {
const [isImpressionLogged, setIsImpressionLogged] = useState(false); const [isImpressionLogged, setIsImpressionLogged] = useState(false);
const [isHidden, setIsHidden] = useState(false); const [isHidden, setIsHidden] = useState(false);
useEffect(() => {
if (!sponsor) {
return;
}
// hide the onboarding strip when the sponsor is visible
isOnboardingStripHidden.set(true);
}, [sponsor]);
useEffect(() => { useEffect(() => {
if (scrollY < SCROLL_DISTANCE || isImpressionLogged) { if (scrollY < SCROLL_DISTANCE || isImpressionLogged) {
return; return;
@ -42,25 +52,29 @@ export function StickyTopSponsor(props: StickyTopSponsorProps) {
onClick={onSponsorClick} onClick={onSponsorClick}
className={cn( className={cn(
'fixed left-0 right-0 top-0 z-[91] flex min-h-[45px] w-full flex-row items-center justify-center px-14 pb-2 pt-1.5 text-base font-medium text-yellow-950', 'fixed left-0 right-0 top-0 z-[91] flex min-h-[45px] w-full flex-row items-center justify-center px-14 pb-2 pt-1.5 text-base font-medium text-yellow-950',
'bg-gradient-to-b from-purple-700 to-purple-800 text-white',
)} )}
style={{
backgroundImage: `linear-gradient(to bottom, ${sponsor.style?.fromColor}, ${sponsor.style?.toColor})`,
color: sponsor.style?.textColor,
}}
> >
<img <img className="h-[23px]" src={sponsor.imageUrl} alt={'ad'} />
className="h-[23px]" <span className="mx-3 truncate">{sponsor.description}</span>
src={'https://tpc.googlesyndication.com/simgad/915843892126714634?'} <button
alt={'ad'} className="flex-truncate rounded-md px-3 py-1 text-sm transition-colors"
/> style={{
<span className="mx-3 truncate"> backgroundColor: sponsor.style?.buttonBackgroundColor,
Register for our free cloud workshop color: sponsor.style?.buttonTextColor,
</span> }}
<button className="flex-truncate rounded-md bg-yellow-400 px-3 py-1 text-sm text-purple-900 transition-colors hover:bg-yellow-300"> >
Register now {sponsor.buttonText}
</button> </button>
<button <button
type="button" type="button"
className="absolute right-5 top-1/2 ml-1 -translate-y-1/2 px-1 py-1 opacity-70 hover:opacity-100" className="absolute right-5 top-1/2 ml-1 -translate-y-1/2 px-1 py-1 opacity-70 hover:opacity-100"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation();
setIsHidden(true); setIsHidden(true);
onSponsorHidden(); onSponsorHidden();

@ -5,3 +5,5 @@ export const sponsorHidden = atom(false);
export const roadmapsDropdownOpen = atom(false); export const roadmapsDropdownOpen = atom(false);
export const navigationDropdownOpen = atom(false); export const navigationDropdownOpen = atom(false);
export const isOnboardingStripHidden = atom(false);
Loading…
Cancel
Save