@@ -4,14 +4,21 @@ import { Logo } from "@/components/sidebar";
4
4
import { TrackedButton } from "@/components/analytics/TrackedButton" ;
5
5
import { usePreviewStore } from "@/hooks/usePreviewStore" ;
6
6
import { cn } from "@repo/design-system/lib/utils" ;
7
- import Link from "next/link" ;
8
7
import { useEffect , useState } from "react" ;
9
8
import { DiscordLogoIcon } from "@radix-ui/react-icons" ;
10
9
import VideoAISparkles from "components/daydream/CustomIcons/VideoAISparkles" ;
10
+ import { useCapacityCheck } from "@/hooks/useCapacityCheck" ;
11
+ import { CapacityNotificationModal } from "@/components/modals/capacity-notification-modal" ;
12
+ import { useRouter } from "next/navigation" ;
13
+ import track from "@/lib/track" ;
14
+ import Link from "next/link" ;
11
15
12
16
export default function Header ( ) {
13
17
const { isPreviewOpen } = usePreviewStore ( ) ;
14
18
const [ scrolled , setScrolled ] = useState ( false ) ;
19
+ const { hasCapacity } = useCapacityCheck ( ) ;
20
+ const [ isCapacityModalOpen , setIsCapacityModalOpen ] = useState ( false ) ;
21
+ const router = useRouter ( ) ;
15
22
16
23
useEffect ( ( ) => {
17
24
const handleScroll = ( ) => {
@@ -24,6 +31,17 @@ export default function Header() {
24
31
} ;
25
32
} , [ ] ) ;
26
33
34
+ const handleCreateClick = ( e : React . MouseEvent ) => {
35
+ e . preventDefault ( ) ;
36
+
37
+ if ( ! hasCapacity ) {
38
+ track ( "capacity_create_blocked" , { location : "header" } ) ;
39
+ setIsCapacityModalOpen ( true ) ;
40
+ } else {
41
+ router . push ( "/create" ) ;
42
+ }
43
+ } ;
44
+
27
45
return (
28
46
< >
29
47
{ /* Custom style to override alwaysAnimatedButton for the circular floating button */ }
@@ -46,26 +64,33 @@ export default function Header() {
46
64
47
65
< header
48
66
className = { cn (
49
- "bg-transparent sticky top-0 z-40 transition-colors duration-300 ease-in-out" ,
67
+ "bg-transparent sticky top-0 z-50 transition-colors duration-300 ease-in-out" ,
50
68
scrolled && "backdrop-filter backdrop-blur-xl bg-opacity-50" ,
51
69
) }
52
70
>
53
71
< nav
54
72
aria-label = "Global"
55
- className = "mx-auto flex items-center justify-between py-4 px-4 sm:px- 6 lg:px-8"
73
+ className = "mx-auto flex items-center justify-between py-4 px-6 lg:px-8"
56
74
>
57
75
< div className = "flex flex-1 items-center" >
58
76
< a href = "#" className = "-m-1.5 p-1.5 flex items-center" >
59
77
< span className = "sr-only" > Daydream by Livepeer</ span >
60
78
< Logo />
61
79
</ a >
62
80
</ div >
63
-
81
+
64
82
{ /* Centered Beta Badge */ }
65
83
< div className = "flex-1 flex justify-center items-center" >
66
- < a href = "https://livepeer.notion.site/15f0a348568781aab037c863d91b05e2" target = "_blank" rel = "noopener noreferrer" className = "flex items-center px-4 py-1 rounded-full border border-blue-200 bg-white/70 backdrop-blur-sm text-blue-600 text-sm font-medium gap-2 shadow-sm hover:bg-white/90 transition-colors" >
84
+ < a
85
+ href = "https://livepeer.notion.site/15f0a348568781aab037c863d91b05e2"
86
+ target = "_blank"
87
+ rel = "noopener noreferrer"
88
+ className = "flex items-center px-4 py-1 rounded-full border border-blue-200 bg-white/70 backdrop-blur-sm text-blue-600 text-sm font-medium gap-2 shadow-sm hover:bg-white/90 transition-colors"
89
+ >
67
90
< span className = "inline-block w-2 h-2 rounded-full bg-blue-500" > </ span >
68
- < span className = "sm:inline hidden" > We're in beta. Send us your feedback and ideas →</ span >
91
+ < span className = "sm:inline hidden" >
92
+ We're in beta. Send us your feedback and ideas →
93
+ </ span >
69
94
< span className = "sm:hidden inline" > Beta</ span >
70
95
</ a >
71
96
</ div >
@@ -88,7 +113,7 @@ export default function Header() {
88
113
< span className = "hidden sm:inline ml-2" > Join Discord</ span >
89
114
</ TrackedButton >
90
115
{ /* Desktop-only Create button */ }
91
- < Link href = "/create" className = "hidden sm:block ml-4" >
116
+ < div className = "hidden sm:block ml-4" onClick = { handleCreateClick } >
92
117
< TrackedButton
93
118
trackingEvent = "explore_header_start_creating_clicked"
94
119
trackingProperties = { { location : "explore_header" } }
@@ -102,17 +127,16 @@ export default function Header() {
102
127
< VideoAISparkles className = { cn ( "text-black !w-10 !h-10" ) } /> { " " }
103
128
Create
104
129
</ TrackedButton >
105
- </ Link >
130
+ </ div >
106
131
</ div >
107
132
</ nav >
108
133
</ header >
109
134
110
135
{ /* Mobile-only floating Create button */ }
111
- < Link
112
- href = "/create"
136
+ < div
113
137
className = { cn (
114
138
"fixed bottom-6 right-6 sm:hidden z-50" ,
115
- isPreviewOpen && "opacity-0 pointer-events-none" ,
139
+ ( isPreviewOpen || ! hasCapacity ) && "opacity-0 pointer-events-none" ,
116
140
) }
117
141
>
118
142
< div className = "rounded-full floating-shadow" >
@@ -121,15 +145,21 @@ export default function Header() {
121
145
trackingProperties = { { location : "explore_header_mobile_fab" } }
122
146
size = "lg"
123
147
className = { cn (
124
- "!rounded-full h-16 w-16 text-black flex items-center justify-center p-0" ,
148
+ "!rounded-full h-20 w-20 text-black flex items-center justify-center p-0" ,
125
149
"alwaysAnimatedButton circular-animated-button forced-white-bg" ,
126
150
isPreviewOpen && "opacity-0 pointer-events-none" ,
127
151
) }
152
+ onClick = { handleCreateClick }
128
153
>
129
- < VideoAISparkles className = { cn ( "text-black !w-12 !h-12 " ) } />
154
+ < VideoAISparkles className = { cn ( "text-black !w-16 !h-16 " ) } />
130
155
</ TrackedButton >
131
156
</ div >
132
- </ Link >
157
+ </ div >
158
+
159
+ < CapacityNotificationModal
160
+ isOpen = { isCapacityModalOpen }
161
+ onClose = { ( ) => setIsCapacityModalOpen ( false ) }
162
+ />
133
163
</ >
134
164
) ;
135
165
}
0 commit comments