11import { useRef , useState } from 'react'
2+ import { AuthButton , AuthField , AuthHeader , AuthInput , AuthRoot , AuthStack } from '@sim/auth-ui'
23import type { DesktopServerConfiguration } from '@sim/desktop-bridge'
3- import {
4- ChipModalBody ,
5- ChipModalDescription ,
6- ChipModalField ,
7- ChipModalFooter ,
8- ChipModalHeader ,
9- ChipModalSurface ,
10- } from '@sim/emcn'
11- import { mountShellModal } from '@/renderer/shell'
124import type { ShellWindowApi } from '@/shared/shell'
135
146interface ServerModalProps {
@@ -22,7 +14,24 @@ function closeWindow() {
2214}
2315
2416function mountServerModal ( element : HTMLDivElement | null ) {
25- return mountShellModal ( element , closeWindow )
17+ if ( ! element ) return
18+ element . querySelector < HTMLInputElement > ( 'input' ) ?. focus ( )
19+ const host = ( window as Window & { simShell ?: ShellWindowApi } ) . simShell
20+ const resize = ( ) => host ?. resizeContent ( Math . ceil ( element . scrollHeight ) )
21+ const observer = new ResizeObserver ( resize )
22+ observer . observe ( element )
23+ const onKey = ( event : KeyboardEvent ) => {
24+ if ( event . key === 'Escape' ) {
25+ event . preventDefault ( )
26+ closeWindow ( )
27+ }
28+ }
29+ document . addEventListener ( 'keydown' , onKey )
30+ resize ( )
31+ return ( ) => {
32+ observer . disconnect ( )
33+ document . removeEventListener ( 'keydown' , onKey )
34+ }
2635}
2736
2837export function ServerModal ( { server, configuration, initialError } : ServerModalProps ) {
@@ -58,50 +67,73 @@ export function ServerModal({ server, configuration, initialError }: ServerModal
5867 }
5968
6069 return (
61- < ChipModalSurface
62- ref = { mountServerModal }
63- role = 'dialog'
64- aria-modal = 'true'
65- aria-labelledby = 'server-title'
66- aria-describedby = 'server-description'
67- className = 'max-h-screen'
68- >
69- < ChipModalHeader
70- onClose = { closeWindow }
71- className = '[-webkit-app-region:drag] [&_button]:[-webkit-app-region:no-drag]'
70+ < AuthRoot >
71+ < div
72+ ref = { mountServerModal }
73+ role = 'dialog'
74+ aria-modal = 'true'
75+ aria-label = 'Sim server'
76+ className = 'au:p-6'
7277 >
73- < span id = 'server-title' > Sim server</ span >
74- </ ChipModalHeader >
75- < ChipModalBody >
76- < ChipModalDescription id = 'server-description' >
77- Point this app at your own Sim deployment. Self-hosted servers must use HTTPS; localhost
78- may use HTTP.
79- </ ChipModalDescription >
80- < ChipModalField
81- type = 'input'
82- inputType = 'url'
83- title = 'Server URL'
84- value = { origin }
85- onChange = { ( value ) => {
86- setOrigin ( value )
87- setError ( undefined )
88- setMessage ( '' )
89- } }
90- autoComplete = 'off'
91- placeholder = 'https://sim.example.com'
92- disabled = { pending }
93- error = { error }
94- hint = { < span role = 'status' > { pending ? 'Connecting…' : message } </ span > }
95- />
96- </ ChipModalBody >
97- < ChipModalFooter
98- onCancel = { closeWindow }
99- primaryAction = { {
100- label : pending ? 'Connecting…' : 'Connect' ,
101- onClick : connect ,
102- disabled : pending || ! origin . trim ( ) ,
103- } }
104- />
105- </ ChipModalSurface >
78+ < AuthStack >
79+ < div className = 'au:[-webkit-app-region:drag]' >
80+ < AuthHeader
81+ title = 'Sim server'
82+ description = 'Connect to your organization’s Sim deployment.'
83+ />
84+ </ div >
85+ < form
86+ onSubmit = { ( event ) => {
87+ event . preventDefault ( )
88+ void connect ( )
89+ } }
90+ className = 'au:space-y-5'
91+ >
92+ < AuthField
93+ htmlFor = 'server-origin'
94+ label = 'Server URL'
95+ errors = { error ? [ error ] : undefined }
96+ hint = {
97+ < >
98+ < span > Use HTTPS for self-hosted servers. Localhost may use HTTP.</ span >
99+ < span role = 'status' > { message && ` ${ message } ` } </ span >
100+ </ >
101+ }
102+ >
103+ < AuthInput
104+ id = 'server-origin'
105+ type = 'url'
106+ value = { origin }
107+ onChange = { ( event ) => {
108+ setOrigin ( event . target . value )
109+ setError ( undefined )
110+ setMessage ( '' )
111+ } }
112+ autoComplete = 'off'
113+ placeholder = 'https://sim.example.com'
114+ disabled = { pending }
115+ error = { Boolean ( error ) }
116+ aria-describedby = 'server-origin-hint'
117+ />
118+ </ AuthField >
119+ < div className = 'au:grid au:grid-cols-2 au:gap-2' >
120+ < AuthButton onClick = { closeWindow } fullWidth >
121+ Cancel
122+ </ AuthButton >
123+ < AuthButton
124+ type = 'submit'
125+ variant = 'primary'
126+ disabled = { ! origin . trim ( ) }
127+ loading = { pending }
128+ loadingLabel = 'Connecting…'
129+ fullWidth
130+ >
131+ Connect
132+ </ AuthButton >
133+ </ div >
134+ </ form >
135+ </ AuthStack >
136+ </ div >
137+ </ AuthRoot >
106138 )
107139}
0 commit comments