88 ChevronDown ,
99 DropdownMenu ,
1010 DropdownMenuContent ,
11+ DropdownMenuGroup ,
1112 DropdownMenuSeparator ,
1213 DropdownMenuTrigger ,
1314 Modal ,
@@ -384,7 +385,7 @@ export function WorkspaceHeader({
384385 </ div >
385386 ) : (
386387 < >
387- < div className = 'flex items-center gap-[8px] px-[2px] py-[2px ]' >
388+ < div className = 'flex items-center gap-[8px] px-[2px] py-[4px ]' >
388389 < div
389390 className = 'flex h-[32px] w-[32px] flex-shrink-0 items-center justify-center rounded-[6px] font-medium text-[12px] text-white'
390391 style = { {
@@ -403,10 +404,113 @@ export function WorkspaceHeader({
403404 </ div >
404405 </ div >
405406
406- < DropdownMenuSeparator />
407+ < DropdownMenuGroup className = 'mt-[4px]' >
408+ < div className = 'flex max-h-[130px] flex-col gap-[2px] overflow-y-auto' >
409+ { workspaces . map ( ( workspace ) => (
410+ < div key = { workspace . id } >
411+ { editingWorkspaceId === workspace . id ? (
412+ < div className = 'flex items-center gap-[8px] rounded-[5px] bg-[var(--surface-active)] px-[8px] py-[5px]' >
413+ < input
414+ ref = { ( el ) => {
415+ if ( el && ! hasInputFocusedRef . current ) {
416+ hasInputFocusedRef . current = true
417+ el . focus ( )
418+ el . select ( )
419+ }
420+ } }
421+ value = { editingName }
422+ onChange = { ( e ) => setEditingName ( e . target . value ) }
423+ onKeyDown = { async ( e ) => {
424+ e . stopPropagation ( )
425+ if ( e . key === 'Enter' ) {
426+ e . preventDefault ( )
427+ setIsListRenaming ( true )
428+ try {
429+ await onRenameWorkspace ( workspace . id , editingName . trim ( ) )
430+ setEditingWorkspaceId ( null )
431+ } finally {
432+ setIsListRenaming ( false )
433+ }
434+ } else if ( e . key === 'Escape' ) {
435+ e . preventDefault ( )
436+ setEditingWorkspaceId ( null )
437+ }
438+ } }
439+ onBlur = { async ( ) => {
440+ if ( ! editingWorkspaceId ) return
441+ const trimmedName = editingName . trim ( )
442+ if ( trimmedName && trimmedName !== workspace . name ) {
443+ setIsListRenaming ( true )
444+ try {
445+ await onRenameWorkspace ( workspace . id , trimmedName )
446+ } finally {
447+ setIsListRenaming ( false )
448+ }
449+ }
450+ setEditingWorkspaceId ( null )
451+ } }
452+ className = 'w-full border-0 bg-transparent p-0 font-medium text-[12px] text-[var(--text-primary)] outline-none selection:bg-[#add6ff] selection:text-[#1b1b1b] focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:selection:bg-[#264f78] dark:selection:text-white'
453+ maxLength = { 100 }
454+ autoComplete = 'off'
455+ autoCorrect = 'off'
456+ autoCapitalize = 'off'
457+ spellCheck = 'false'
458+ disabled = { isListRenaming }
459+ onClick = { ( e ) => {
460+ e . stopPropagation ( )
461+ } }
462+ />
463+ </ div >
464+ ) : (
465+ < div
466+ className = { cn (
467+ 'group flex cursor-pointer select-none items-center gap-[8px] rounded-[5px] px-[8px] py-[5px] font-medium text-[12px] text-[var(--text-body)] outline-none transition-colors hover:bg-[var(--surface-active)]' ,
468+ workspace . id === workspaceId && 'bg-[var(--surface-active)]'
469+ ) }
470+ onClick = { ( ) => onWorkspaceSwitch ( workspace ) }
471+ onContextMenu = { ( e ) => handleContextMenu ( e , workspace ) }
472+ >
473+ < span className = 'min-w-0 flex-1 truncate' > { workspace . name } </ span >
474+ < button
475+ type = 'button'
476+ aria-label = 'Workspace options'
477+ onMouseDown = { ( ) => {
478+ isContextMenuOpeningRef . current = true
479+ } }
480+ onClick = { ( e ) => {
481+ e . preventDefault ( )
482+ e . stopPropagation ( )
483+ const rect = e . currentTarget . getBoundingClientRect ( )
484+ openContextMenuAt ( workspace , rect . right , rect . top )
485+ } }
486+ className = 'flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center rounded-[4px] opacity-0 transition-opacity hover:bg-[var(--surface-7)] group-hover:opacity-100'
487+ >
488+ < MoreHorizontal className = 'h-[14px] w-[14px] text-[var(--text-tertiary)]' />
489+ </ button >
490+ </ div >
491+ ) }
492+ </ div >
493+ ) ) }
494+ </ div >
495+
496+ < button
497+ type = 'button'
498+ className = 'flex w-full cursor-pointer select-none items-center gap-[8px] rounded-[5px] px-[8px] py-[5px] font-medium text-[12px] text-[var(--text-body)] outline-none transition-colors hover:bg-[var(--surface-active)] disabled:pointer-events-none disabled:opacity-50'
499+ onClick = { ( e ) => {
500+ e . stopPropagation ( )
501+ setIsWorkspaceMenuOpen ( false )
502+ setIsCreateModalOpen ( true )
503+ } }
504+ disabled = { isCreatingWorkspace }
505+ >
506+ < Plus className = 'h-[14px] w-[14px] shrink-0 text-[var(--text-icon)]' />
507+ Create new workspace
508+ </ button >
509+ </ DropdownMenuGroup >
407510
408511 { ! isInvitationsDisabled && (
409512 < >
513+ < DropdownMenuSeparator />
410514 < button
411515 type = 'button'
412516 className = 'flex w-full cursor-pointer select-none items-center gap-[8px] rounded-[5px] px-[8px] py-[5px] font-medium text-[12px] text-[var(--text-body)] outline-none transition-colors hover:bg-[var(--surface-active)]'
@@ -418,116 +522,8 @@ export function WorkspaceHeader({
418522 < UserPlus className = 'h-[14px] w-[14px] shrink-0 text-[var(--text-icon)]' />
419523 Invite members
420524 </ button >
421- < DropdownMenuSeparator />
422525 </ >
423526 ) }
424-
425- < div className = 'px-[8px] py-[5px] font-medium text-[11px] text-[var(--text-icon)]' >
426- All workspaces
427- </ div >
428- < div className = 'flex max-h-[130px] flex-col gap-[2px] overflow-y-auto' >
429- { workspaces . map ( ( workspace ) => (
430- < div key = { workspace . id } >
431- { editingWorkspaceId === workspace . id ? (
432- < div className = 'flex items-center gap-[8px] rounded-[5px] bg-[var(--surface-active)] px-[8px] py-[5px]' >
433- < input
434- ref = { ( el ) => {
435- if ( el && ! hasInputFocusedRef . current ) {
436- hasInputFocusedRef . current = true
437- el . focus ( )
438- el . select ( )
439- }
440- } }
441- value = { editingName }
442- onChange = { ( e ) => setEditingName ( e . target . value ) }
443- onKeyDown = { async ( e ) => {
444- e . stopPropagation ( )
445- if ( e . key === 'Enter' ) {
446- e . preventDefault ( )
447- setIsListRenaming ( true )
448- try {
449- await onRenameWorkspace ( workspace . id , editingName . trim ( ) )
450- setEditingWorkspaceId ( null )
451- } finally {
452- setIsListRenaming ( false )
453- }
454- } else if ( e . key === 'Escape' ) {
455- e . preventDefault ( )
456- setEditingWorkspaceId ( null )
457- }
458- } }
459- onBlur = { async ( ) => {
460- if ( ! editingWorkspaceId ) return
461- const trimmedName = editingName . trim ( )
462- if ( trimmedName && trimmedName !== workspace . name ) {
463- setIsListRenaming ( true )
464- try {
465- await onRenameWorkspace ( workspace . id , trimmedName )
466- } finally {
467- setIsListRenaming ( false )
468- }
469- }
470- setEditingWorkspaceId ( null )
471- } }
472- className = 'w-full border-0 bg-transparent p-0 font-medium text-[12px] text-[var(--text-primary)] outline-none selection:bg-[#add6ff] selection:text-[#1b1b1b] focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 dark:selection:bg-[#264f78] dark:selection:text-white'
473- maxLength = { 100 }
474- autoComplete = 'off'
475- autoCorrect = 'off'
476- autoCapitalize = 'off'
477- spellCheck = 'false'
478- disabled = { isListRenaming }
479- onClick = { ( e ) => {
480- e . stopPropagation ( )
481- } }
482- />
483- </ div >
484- ) : (
485- < div
486- className = { cn (
487- 'group flex cursor-pointer select-none items-center gap-[8px] rounded-[5px] px-[8px] py-[5px] font-medium text-[12px] text-[var(--text-body)] outline-none transition-colors hover:bg-[var(--surface-active)]' ,
488- workspace . id === workspaceId && 'bg-[var(--surface-active)]'
489- ) }
490- onClick = { ( ) => onWorkspaceSwitch ( workspace ) }
491- onContextMenu = { ( e ) => handleContextMenu ( e , workspace ) }
492- >
493- < span className = 'min-w-0 flex-1 truncate' > { workspace . name } </ span >
494- < button
495- type = 'button'
496- aria-label = 'Workspace options'
497- onMouseDown = { ( ) => {
498- isContextMenuOpeningRef . current = true
499- } }
500- onClick = { ( e ) => {
501- e . preventDefault ( )
502- e . stopPropagation ( )
503- const rect = e . currentTarget . getBoundingClientRect ( )
504- openContextMenuAt ( workspace , rect . right , rect . top )
505- } }
506- className = 'flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center rounded-[4px] opacity-0 transition-opacity hover:bg-[var(--surface-7)] group-hover:opacity-100'
507- >
508- < MoreHorizontal className = 'h-[14px] w-[14px] text-[var(--text-tertiary)]' />
509- </ button >
510- </ div >
511- ) }
512- </ div >
513- ) ) }
514- </ div >
515-
516- < DropdownMenuSeparator />
517-
518- < button
519- type = 'button'
520- className = 'flex w-full cursor-pointer select-none items-center gap-[8px] rounded-[5px] px-[8px] py-[5px] font-medium text-[12px] text-[var(--text-body)] outline-none transition-colors hover:bg-[var(--surface-active)] disabled:pointer-events-none disabled:opacity-50'
521- onClick = { ( e ) => {
522- e . stopPropagation ( )
523- setIsWorkspaceMenuOpen ( false )
524- setIsCreateModalOpen ( true )
525- } }
526- disabled = { isCreatingWorkspace }
527- >
528- < Plus className = 'h-[14px] w-[14px] shrink-0 text-[var(--text-icon)]' />
529- Create new workspace
530- </ button >
531527 </ >
532528 ) }
533529 </ DropdownMenuContent >
0 commit comments