@@ -191,6 +191,9 @@ let workspaceTabRenameState = {
191191let workspaceTabAddMenuOpen = false
192192let isRenderingWorkspaceTabs = false
193193let hasPendingWorkspaceTabsRender = false
194+ let draggedWorkspaceTabId = ''
195+ let dragOverWorkspaceTabId = ''
196+ let suppressWorkspaceTabClick = false
194197const clipboardSupported = Boolean ( navigator . clipboard ?. writeText )
195198const githubPrOpenIcon = {
196199 viewBox : '0 0 16 16' ,
@@ -1623,6 +1626,11 @@ const setWorkspaceTabAddMenuOpen = isOpen => {
16231626 }
16241627}
16251628
1629+ const clearWorkspaceTabDragState = ( ) => {
1630+ draggedWorkspaceTabId = ''
1631+ dragOverWorkspaceTabId = ''
1632+ }
1633+
16261634const renderWorkspaceTabs = ( ) => {
16271635 if ( ! ( workspaceTabsStrip instanceof HTMLElement ) ) {
16281636 return
@@ -1643,11 +1651,21 @@ const renderWorkspaceTabs = () => {
16431651
16441652 for ( const tab of tabs ) {
16451653 const isActive = tab . id === activeTabId
1654+ const isRenaming = workspaceTabRenameState . tabId === tab . id
16461655 const tabContainer = document . createElement ( 'li' )
16471656 tabContainer . className = 'workspace-tab'
16481657 tabContainer . dataset . active = isActive ? 'true' : 'false'
16491658 tabContainer . dataset . tabId = tab . id
1659+ tabContainer . setAttribute ( 'aria-label' , `Workspace tab ${ tab . name } ` )
1660+ tabContainer . draggable = ! isRenaming
1661+ tabContainer . dataset . dragOver =
1662+ dragOverWorkspaceTabId && dragOverWorkspaceTabId === tab . id ? 'true' : 'false'
16501663 tabContainer . addEventListener ( 'click' , event => {
1664+ if ( suppressWorkspaceTabClick ) {
1665+ suppressWorkspaceTabClick = false
1666+ return
1667+ }
1668+
16511669 const clickTarget = event . target
16521670 if ( ! ( clickTarget instanceof Element ) ) {
16531671 return
@@ -1661,8 +1679,72 @@ const renderWorkspaceTabs = () => {
16611679
16621680 setActiveWorkspaceTab ( tab . id )
16631681 } )
1682+ if ( ! isRenaming ) {
1683+ tabContainer . addEventListener ( 'dragstart' , event => {
1684+ draggedWorkspaceTabId = tab . id
1685+ dragOverWorkspaceTabId = ''
1686+ suppressWorkspaceTabClick = true
1687+ if ( event . dataTransfer ) {
1688+ event . dataTransfer . effectAllowed = 'move'
1689+ event . dataTransfer . setData ( 'text/plain' , tab . id )
1690+ }
1691+ } )
1692+ tabContainer . addEventListener ( 'dragend' , ( ) => {
1693+ clearWorkspaceTabDragState ( )
1694+ queueMicrotask ( ( ) => {
1695+ suppressWorkspaceTabClick = false
1696+ } )
1697+ renderWorkspaceTabs ( )
1698+ } )
1699+ tabContainer . addEventListener ( 'dragover' , event => {
1700+ if ( ! draggedWorkspaceTabId || draggedWorkspaceTabId === tab . id ) {
1701+ return
1702+ }
1703+
1704+ event . preventDefault ( )
1705+ if ( event . dataTransfer ) {
1706+ event . dataTransfer . dropEffect = 'move'
1707+ }
1708+
1709+ if ( dragOverWorkspaceTabId !== tab . id ) {
1710+ dragOverWorkspaceTabId = tab . id
1711+ tabContainer . dataset . dragOver = 'true'
1712+ }
1713+ } )
1714+ tabContainer . addEventListener ( 'dragleave' , event => {
1715+ const relatedTarget = event . relatedTarget
1716+ if ( relatedTarget instanceof Node && tabContainer . contains ( relatedTarget ) ) {
1717+ return
1718+ }
1719+
1720+ if ( dragOverWorkspaceTabId === tab . id ) {
1721+ dragOverWorkspaceTabId = ''
1722+ tabContainer . dataset . dragOver = 'false'
1723+ }
1724+ } )
1725+ tabContainer . addEventListener ( 'drop' , event => {
1726+ event . preventDefault ( )
1727+
1728+ if ( ! draggedWorkspaceTabId || draggedWorkspaceTabId === tab . id ) {
1729+ clearWorkspaceTabDragState ( )
1730+ renderWorkspaceTabs ( )
1731+ return
1732+ }
1733+
1734+ persistActiveTabEditorContent ( )
1735+
1736+ const moved = workspaceTabsState . moveTabBefore ( draggedWorkspaceTabId , tab . id )
1737+ clearWorkspaceTabDragState ( )
1738+ renderWorkspaceTabs ( )
1739+
1740+ if ( ! moved ) {
1741+ return
1742+ }
1743+
1744+ queueWorkspaceSave ( )
1745+ } )
1746+ }
16641747
1665- const isRenaming = workspaceTabRenameState . tabId === tab . id
16661748 if ( isRenaming ) {
16671749 const renameInput = document . createElement ( 'input' )
16681750 renameInput . className = 'workspace-tab__name-input'
0 commit comments