@@ -35,12 +35,19 @@ export function CloneAccountModal({
3535 onCloned,
3636} : CloneAccountModalProps ) {
3737 const [ suffix , setSuffix ] = useState ( '' ) ;
38+ const [ displayName , setDisplayName ] = useState ( '' ) ;
3839 const [ isChecking , setIsChecking ] = useState ( false ) ;
3940 const [ isAvailable , setIsAvailable ] = useState < boolean | null > ( null ) ;
4041 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
4142 const [ submitError , setSubmitError ] = useState < string | null > ( null ) ;
4243 const [ isLoadingSuggestion , setIsLoadingSuggestion ] = useState ( false ) ;
4344
45+ const trimmedSuffix = suffix . trim ( ) ;
46+ const trimmedDisplayName = displayName . trim ( ) ;
47+ const displayNamePlaceholder = trimmedSuffix
48+ ? `${ sourceServer . name } (${ trimmedSuffix } )`
49+ : `${ sourceServer . name } (work)` ;
50+
4451 const previewId = deriveCloneServerId ( sourceServer . id , suffix ) ;
4552 const previewAlias = deriveCloneAlias ( suffix ) ;
4653 const hasSuffix = suffix . trim ( ) . length > 0 ;
@@ -131,34 +138,51 @@ export function CloneAccountModal({
131138 setSubmitError ( null ) ;
132139
133140 try {
134- const cloned = await cloneServer ( spaceId , sourceServer . id , suffix ) ;
141+ const cloned = await cloneServer (
142+ spaceId ,
143+ sourceServer . id ,
144+ suffix ,
145+ undefined ,
146+ trimmedDisplayName . length > 0 ? trimmedDisplayName : undefined
147+ ) ;
135148 onCloned ( cloned ) ;
136149 onClose ( ) ;
137150 } catch ( e ) {
138151 setSubmitError ( String ( e ) ) ;
139152 } finally {
140153 setIsSubmitting ( false ) ;
141154 }
142- } , [ hasSuffix , hasCollision , isChecking , spaceId , sourceServer . id , suffix , onCloned , onClose ] ) ;
155+ } , [
156+ hasSuffix ,
157+ hasCollision ,
158+ isChecking ,
159+ spaceId ,
160+ sourceServer . id ,
161+ suffix ,
162+ trimmedDisplayName ,
163+ onCloned ,
164+ onClose ,
165+ ] ) ;
143166
144167 if ( ! open ) {
145168 return null ;
146169 }
147170
148- const canSubmit = hasSuffix && ! hasCollision && ! isChecking && ! isSubmitting && ! isLoadingSuggestion ;
171+ const canSubmit =
172+ hasSuffix && ! hasCollision && ! isChecking && ! isSubmitting && ! isLoadingSuggestion ;
149173
150174 return (
151175 < div
152- className = "fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 p-4"
176+ className = "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4 backdrop-blur-sm "
153177 data-testid = "clone-account-modal-overlay"
154178 >
155179 < div
156- className = "dropdown-menu w-full max-w-md p-6 animate-in fade-in scale-in duration-150"
180+ className = "dropdown-menu animate-in fade-in scale-in w-full max-w-md p-6 duration-150"
157181 data-testid = "clone-account-modal"
158182 >
159- < div className = "flex items-start justify-between gap-3 mb-4 " >
183+ < div className = "mb-4 flex items-start justify-between gap-3" >
160184 < div className = "flex items-center gap-3" >
161- < div className = "p-2 rounded-lg bg-[rgb(var(--primary))]/10" >
185+ < div className = "rounded-lg bg-[rgb(var(--primary))]/10 p-2 " >
162186 < Copy className = "h-5 w-5 text-[rgb(var(--primary))]" />
163187 </ div >
164188 < div >
@@ -172,7 +196,7 @@ export function CloneAccountModal({
172196 </ div >
173197 < button
174198 onClick = { onClose }
175- className = "p-1 rounded hover:bg -[rgb(var(--surface-hover ))] text- [rgb(var(--muted ))] transition-colors "
199+ className = "rounded p-1 text -[rgb(var(--muted ))] transition-colors hover:bg- [rgb(var(--surface-hover ))]"
176200 aria-label = "Close"
177201 data-testid = "clone-account-close-btn"
178202 >
@@ -181,14 +205,36 @@ export function CloneAccountModal({
181205 </ div >
182206
183207 < div className = "space-y-4" >
208+ < div >
209+ < label
210+ htmlFor = "clone-display-name"
211+ className = "mb-1 block text-sm font-medium text-[rgb(var(--foreground))]"
212+ >
213+ Display name
214+ </ label >
215+ < p className = "mb-2 text-xs text-[rgb(var(--muted))]" >
216+ Shown in My Servers only. Leave blank to use the default.
217+ </ p >
218+ < input
219+ id = "clone-display-name"
220+ type = "text"
221+ value = { displayName }
222+ onChange = { ( e ) => setDisplayName ( e . target . value ) }
223+ placeholder = { displayNamePlaceholder }
224+ className = "input w-full"
225+ disabled = { isSubmitting }
226+ data-testid = "clone-display-name-input"
227+ />
228+ </ div >
229+
184230 < div >
185231 < label
186232 htmlFor = "clone-suffix"
187- className = "block text-sm font-medium text-[rgb(var(--foreground))] mb-1 "
233+ className = "mb-1 block text-sm font-medium text-[rgb(var(--foreground))]"
188234 >
189235 Account label
190236 </ label >
191- < p className = "text-xs text-[rgb(var(--muted))] mb-2 " >
237+ < p className = "mb-2 text-xs text-[rgb(var(--muted))]" >
192238 Used in the server ID and tool prefix (e.g. work, personal)
193239 </ p >
194240 < input
@@ -202,21 +248,24 @@ export function CloneAccountModal({
202248 data-testid = "clone-suffix-input"
203249 />
204250 { hasCollision && (
205- < p className = "text-xs text-[rgb(var(--error))] mt-1" data-testid = "clone-collision-error" >
251+ < p
252+ className = "mt-1 text-xs text-[rgb(var(--error))]"
253+ data-testid = "clone-collision-error"
254+ >
206255 An account with this label already exists in this space
207256 </ p >
208257 ) }
209258 </ div >
210259
211260 < div >
212- < p className = "text-xs font-medium text-[rgb(var(--muted))] mb-2 " > Suggestions</ p >
261+ < p className = "mb-2 text-xs font-medium text-[rgb(var(--muted))]" > Suggestions</ p >
213262 < div className = "flex flex-wrap gap-2" >
214263 { CLONE_SUFFIX_SUGGESTIONS . map ( ( suggestion ) => (
215264 < button
216265 key = { suggestion }
217266 type = "button"
218267 onClick = { ( ) => setSuffix ( suggestion ) }
219- className = { `px-2.5 py-1 text-xs rounded-md border transition-colors ${
268+ className = { `rounded-md border px-2.5 py-1 text-xs transition-colors ${
220269 suffix === suggestion
221270 ? 'border-[rgb(var(--primary))] bg-[rgb(var(--primary))]/10 text-[rgb(var(--primary))]'
222271 : 'border-[rgb(var(--border))] text-[rgb(var(--muted))] hover:bg-[rgb(var(--surface-hover))]'
@@ -230,14 +279,16 @@ export function CloneAccountModal({
230279 </ div >
231280
232281 { hasSuffix && (
233- < div className = "rounded-lg border border-[rgb(var(--border-subtle))] bg-[rgb(var(--surface-dim))] p-3 space-y-2 " >
282+ < div className = "space-y-2 rounded-lg border border-[rgb(var(--border-subtle))] bg-[rgb(var(--surface-dim))] p-3" >
234283 < div className = "flex items-center justify-between gap-2 text-sm" >
235284 < span className = "text-[rgb(var(--muted))]" > Server ID</ span >
236- < code className = "text-xs font-mono text-[rgb(var(--foreground))]" > { previewId || '—' } </ code >
285+ < code className = "font-mono text-xs text-[rgb(var(--foreground))]" >
286+ { previewId || '—' }
287+ </ code >
237288 </ div >
238289 < div className = "flex items-center justify-between gap-2 text-sm" >
239290 < span className = "text-[rgb(var(--muted))]" > Tool prefix</ span >
240- < code className = "text-xs font-mono text-[rgb(var(--foreground))]" >
291+ < code className = "font-mono text-xs text-[rgb(var(--foreground))]" >
241292 { previewAlias ? `${ previewAlias } _*` : '—' }
242293 </ code >
243294 </ div >
@@ -264,7 +315,7 @@ export function CloneAccountModal({
264315 < div className = "flex justify-end gap-2 pt-2" >
265316 < button
266317 onClick = { onClose }
267- className = "px-4 py-2 text-sm rounded-lg border border-[rgb(var(--border))] text-[rgb(var(--muted))] hover:bg-[rgb(var(--surface-hover))] transition-colors "
318+ className = "rounded-lg border border-[rgb(var(--border))] px-4 py-2 text-sm text- [rgb(var(--muted))] transition-colors hover:bg-[rgb(var(--surface-hover))]"
268319 disabled = { isSubmitting }
269320 data-testid = "clone-cancel-btn"
270321 >
@@ -273,7 +324,7 @@ export function CloneAccountModal({
273324 < button
274325 onClick = { handleSubmit }
275326 disabled = { ! canSubmit }
276- className = "px-4 py -2 text-sm rounded-lg bg-[rgb(var(--primary))] text-[rgb(var(--primary-foreground))] hover:bg-[rgb(var(--primary-hover))] disabled:opacity-50 transition-colors flex items-center gap-2 "
327+ className = "flex items-center gap -2 rounded-lg bg-[rgb(var(--primary))] px-4 py-2 text-sm text- [rgb(var(--primary-foreground))] transition-colors hover:bg-[rgb(var(--primary-hover))] disabled:opacity-50"
277328 data-testid = "clone-submit-btn"
278329 >
279330 { isSubmitting && < Loader2 className = "h-4 w-4 animate-spin" /> }
0 commit comments