55} from '@studio/common/ai/sessions/entry-types' ;
66import { QueryClientProvider } from '@tanstack/react-query' ;
77import { Spinner } from '@wordpress/components' ;
8- import { createInterpolateElement } from '@wordpress/element' ;
98import { __ } from '@wordpress/i18n' ;
10- import { chevronDown } from '@wordpress/icons' ;
9+ import { check , chevronDown , Icon as WpIcon } from '@wordpress/icons' ;
1110import { privateApis } from '@wordpress/theme' ;
1211import { Button as UiButton , Icon } from '@wordpress/ui' ;
1312import {
@@ -22,6 +21,9 @@ import {
2221} from 'react' ;
2322import { ArrowIcon } from 'src/components/arrow-icon' ;
2423import Button from 'src/components/button' ;
24+ import { IllustrationGrid } from 'src/components/illustration-grid' ;
25+ import offlineIcon from 'src/components/offline-icon' ;
26+ import { Tooltip } from 'src/components/tooltip' ;
2527import { useAuth } from 'src/hooks/use-auth' ;
2628import { useOffline } from 'src/hooks/use-offline' ;
2729import { cx } from 'src/lib/cx' ;
@@ -33,6 +35,7 @@ import { queryClient } from './query-client';
3335import { QueuedPrompts } from './queued-prompts' ;
3436import { isScrolledToBottom } from './scroll-utils' ;
3537import { SiteCreatedDialog } from './site-created-dialog' ;
38+ import { StudioCodeTabImage } from './studio-code-tab-image' ;
3639import styles from './style.module.css' ;
3740import { AgentRunProvider , useAgentRun } from './use-agent-run' ;
3841import { useExamplePrompts } from './use-example-prompts' ;
@@ -101,27 +104,80 @@ function SessionHeader( { onNewConversation }: { onNewConversation: () => void }
101104 ) ;
102105}
103106
104- function UnauthenticatedNotice ( { onAuthenticate } : { onAuthenticate : ( ) => void } ) {
107+ function NoAuth ( ) {
108+ const isOffline = useOffline ( ) ;
109+ const { authenticate } = useAuth ( ) ;
110+ const offlineMessage = __ ( "You're currently offline." ) ;
111+
105112 return (
106- < div className = "px-4 pb-4" >
107- < div className = "p-3 rounded border border-frame-border bg-frame/45" >
108- < div className = "mb-3 a8c-label-semibold" > { __ ( 'Hold up!' ) } </ div >
109- < div className = "mb-1" >
110- { __ ( 'You need to log in to your WordPress.com account to use Studio Code.' ) }
111- </ div >
112- < div className = "mb-3" >
113- { createInterpolateElement (
114- __ ( "If you don't have an account yet, <a>create one for free</a>." ) ,
115- {
116- a : < Button variant = "link" onClick = { ( ) => getIpcApi ( ) . authenticate ( true ) } /> ,
117- }
113+ < div className = "p-8 flex justify-between max-w-3xl gap-4 overflow-hidden" >
114+ < div className = "flex flex-col" >
115+ < div className = "a8c-subtitle mb-1" > { __ ( 'Build with Studio Code' ) } </ div >
116+ < div className = "w-[40ch] text-frame-text-secondary a8c-body" >
117+ { __ (
118+ 'Your AI coding agent for WordPress. Describe what you want and Studio Code builds, edits, and debugs your site.'
118119 ) }
119120 </ div >
120- < Button variant = "primary" onClick = { onAuthenticate } >
121- { __ ( 'Log in to WordPress.com' ) }
122- < ArrowIcon />
123- </ Button >
121+ < div className = "mt-6" >
122+ { [
123+ __ ( 'Create and edit themes, plugins, and content.' ) ,
124+ __ ( 'Debug issues and run WP-CLI commands.' ) ,
125+ __ ( 'Build with built-in feedback loops and agent skills.' ) ,
126+ ] . map ( ( text ) => (
127+ < div key = { text } className = "text-frame-text-secondary a8c-body flex items-center" >
128+ < WpIcon className = "fill-frame-theme ltr:mr-2 rtl:ml-2 shrink-0" icon = { check } />
129+ { text }
130+ </ div >
131+ ) ) }
132+ </ div >
133+ < div className = "mt-8" >
134+ < Tooltip disabled = { ! isOffline } icon = { offlineIcon } text = { offlineMessage } >
135+ < Button
136+ aria-description = { isOffline ? offlineMessage : '' }
137+ aria-disabled = { isOffline }
138+ variant = "primary"
139+ onClick = { ( ) => {
140+ if ( isOffline ) {
141+ return ;
142+ }
143+ authenticate ( ) ;
144+ } }
145+ >
146+ { __ ( 'Log in to WordPress.com' ) }
147+ < ArrowIcon />
148+ </ Button >
149+ </ Tooltip >
150+ </ div >
151+ < div className = "mt-3 w-[40ch] text-frame-text-secondary a8c-body" >
152+ < Tooltip
153+ disabled = { ! isOffline }
154+ icon = { offlineIcon }
155+ text = { offlineMessage }
156+ placement = "bottom-start"
157+ >
158+ < span >
159+ { __ ( 'A WordPress.com account is required to use Studio Code.' ) } { ' ' }
160+ < Button
161+ aria-description = { isOffline ? offlineMessage : '' }
162+ aria-disabled = { isOffline }
163+ className = "!p-0 text-frame-theme hover:opacity-80 h-auto inline-flex items-center"
164+ onClick = { ( ) => {
165+ if ( isOffline ) {
166+ return ;
167+ }
168+ getIpcApi ( ) . authenticate ( true ) ;
169+ } }
170+ >
171+ { __ ( 'Create a free account' ) }
172+ < ArrowIcon />
173+ </ Button >
174+ </ span >
175+ </ Tooltip >
176+ </ div >
124177 </ div >
178+ < IllustrationGrid >
179+ < StudioCodeTabImage />
180+ </ IllustrationGrid >
125181 </ div >
126182 ) ;
127183}
@@ -377,11 +433,10 @@ function SessionContent( { selectedSite }: { selectedSite: SiteDetails } ) {
377433}
378434
379435function SessionGate ( { selectedSite } : { selectedSite : SiteDetails } ) {
380- const { isAuthenticated, authenticate } = useAuth ( ) ;
381- const isOffline = useOffline ( ) ;
436+ const { isAuthenticated } = useAuth ( ) ;
382437
383- if ( ! isAuthenticated && ! isOffline ) {
384- return < UnauthenticatedNotice onAuthenticate = { authenticate } /> ;
438+ if ( ! isAuthenticated ) {
439+ return < NoAuth /> ;
385440 }
386441
387442 return < SessionContent selectedSite = { selectedSite } /> ;
0 commit comments