feat(app): drag-and-drop reorder across titlebar slots #689

Description

@jeonghun-jj-lee

Important

Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

Acceptance Criteria

  • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
  • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
  • Dragging a control within the right slot reorders it among right-slot controls
  • Dragging a control within the left slot reorders it among left-slot controls
  • Dragging a control past the tab strip's left edge moves it to the left slot
  • Dragging a control past the tab strip's right edge moves it to the right slot
  • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
  • On drop, the titlebarLayout setting is updated immediately
  • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
  • Dropping a control in the same position (no-op drag) does not trigger a settings write
  • Outside edit mode, no DnD context is active and controls are not draggable

Testing Decisions

Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

Key Decisions

  • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
  • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
  • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

Constraints & Invariants

  • The DnD context is only active during edit mode -- never outside it
  • left.concat(right) must still contain exactly the five canonical IDs after every drop
  • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
  • Drop indicators must not shift the layout or change button positions until the actual drop

Prior Art

  • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
  • @dnd-kit/solid package -- already in the dependency tree
  • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

Source

Part of #684
Blocked by #687
Blocked by #688

Metadata

Metadata

Labels

afkImplementable without human interactionenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
     blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    
    Skip to content

    feat(app): drag-and-drop reorder across titlebar slots #689

    Description

    @jeonghun-jj-lee

    Important

    Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

    Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

    Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

    Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

    Acceptance Criteria

    • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
    • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
    • Dragging a control within the right slot reorders it among right-slot controls
    • Dragging a control within the left slot reorders it among left-slot controls
    • Dragging a control past the tab strip's left edge moves it to the left slot
    • Dragging a control past the tab strip's right edge moves it to the right slot
    • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
    • On drop, the titlebarLayout setting is updated immediately
    • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
    • Dropping a control in the same position (no-op drag) does not trigger a settings write
    • Outside edit mode, no DnD context is active and controls are not draggable

    Testing Decisions

    Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

    Key Decisions

    • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
    • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
    • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

    Constraints & Invariants

    • The DnD context is only active during edit mode -- never outside it
    • left.concat(right) must still contain exactly the five canonical IDs after every drop
    • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
    • Drop indicators must not shift the layout or change button positions until the actual drop

    Prior Art

    • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
    • @dnd-kit/solid package -- already in the dependency tree
    • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

    Source

    Part of #684
    Blocked by #687
    Blocked by #688

    Metadata

    Metadata

    Labels

    afkImplementable without human interactionenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
      Skip to content

      feat(app): drag-and-drop reorder across titlebar slots #689

      Description

      @jeonghun-jj-lee

      Important

      Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

      Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

      Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

      Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

      Acceptance Criteria

      • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
      • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
      • Dragging a control within the right slot reorders it among right-slot controls
      • Dragging a control within the left slot reorders it among left-slot controls
      • Dragging a control past the tab strip's left edge moves it to the left slot
      • Dragging a control past the tab strip's right edge moves it to the right slot
      • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
      • On drop, the titlebarLayout setting is updated immediately
      • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
      • Dropping a control in the same position (no-op drag) does not trigger a settings write
      • Outside edit mode, no DnD context is active and controls are not draggable

      Testing Decisions

      Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

      Key Decisions

      • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
      • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
      • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

      Constraints & Invariants

      • The DnD context is only active during edit mode -- never outside it
      • left.concat(right) must still contain exactly the five canonical IDs after every drop
      • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
      • Drop indicators must not shift the layout or change button positions until the actual drop

      Prior Art

      • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
      • @dnd-kit/solid package -- already in the dependency tree
      • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

      Source

      Part of #684
      Blocked by #687
      Blocked by #688

      Metadata

      Metadata

      Labels

      afkImplementable without human interactionenhancementNew feature or request

      Type

      No type

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions

        , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
        Skip to content

        feat(app): drag-and-drop reorder across titlebar slots #689

        Description

        @jeonghun-jj-lee

        Important

        Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

        Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

        Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

        Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

        Acceptance Criteria

        • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
        • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
        • Dragging a control within the right slot reorders it among right-slot controls
        • Dragging a control within the left slot reorders it among left-slot controls
        • Dragging a control past the tab strip's left edge moves it to the left slot
        • Dragging a control past the tab strip's right edge moves it to the right slot
        • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
        • On drop, the titlebarLayout setting is updated immediately
        • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
        • Dropping a control in the same position (no-op drag) does not trigger a settings write
        • Outside edit mode, no DnD context is active and controls are not draggable

        Testing Decisions

        Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

        Key Decisions

        • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
        • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
        • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

        Constraints & Invariants

        • The DnD context is only active during edit mode -- never outside it
        • left.concat(right) must still contain exactly the five canonical IDs after every drop
        • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
        • Drop indicators must not shift the layout or change button positions until the actual drop

        Prior Art

        • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
        • @dnd-kit/solid package -- already in the dependency tree
        • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

        Source

        Part of #684
        Blocked by #687
        Blocked by #688

        Metadata

        Metadata

        Labels

        afkImplementable without human interactionenhancementNew feature or request

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
          Skip to content

          feat(app): drag-and-drop reorder across titlebar slots #689

          Description

          @jeonghun-jj-lee

          Important

          Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

          Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

          Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

          Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

          Acceptance Criteria

          • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
          • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
          • Dragging a control within the right slot reorders it among right-slot controls
          • Dragging a control within the left slot reorders it among left-slot controls
          • Dragging a control past the tab strip's left edge moves it to the left slot
          • Dragging a control past the tab strip's right edge moves it to the right slot
          • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
          • On drop, the titlebarLayout setting is updated immediately
          • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
          • Dropping a control in the same position (no-op drag) does not trigger a settings write
          • Outside edit mode, no DnD context is active and controls are not draggable

          Testing Decisions

          Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

          Key Decisions

          • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
          • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
          • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

          Constraints & Invariants

          • The DnD context is only active during edit mode -- never outside it
          • left.concat(right) must still contain exactly the five canonical IDs after every drop
          • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
          • Drop indicators must not shift the layout or change button positions until the actual drop

          Prior Art

          • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
          • @dnd-kit/solid package -- already in the dependency tree
          • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

          Source

          Part of #684
          Blocked by #687
          Blocked by #688

          Metadata

          Metadata

          Labels

          afkImplementable without human interactionenhancementNew feature or request

          Type

          No type

          Projects

          No projects

            Milestone

            No milestone

            Relationships

            None yet

            Development

            No branches or pull requests

            Issue actions

            , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
            Skip to content

            feat(app): drag-and-drop reorder across titlebar slots #689

            Description

            @jeonghun-jj-lee

            Important

            Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

            Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

            Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

            Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

            Acceptance Criteria

            • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
            • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
            • Dragging a control within the right slot reorders it among right-slot controls
            • Dragging a control within the left slot reorders it among left-slot controls
            • Dragging a control past the tab strip's left edge moves it to the left slot
            • Dragging a control past the tab strip's right edge moves it to the right slot
            • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
            • On drop, the titlebarLayout setting is updated immediately
            • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
            • Dropping a control in the same position (no-op drag) does not trigger a settings write
            • Outside edit mode, no DnD context is active and controls are not draggable

            Testing Decisions

            Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

            Key Decisions

            • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
            • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
            • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

            Constraints & Invariants

            • The DnD context is only active during edit mode -- never outside it
            • left.concat(right) must still contain exactly the five canonical IDs after every drop
            • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
            • Drop indicators must not shift the layout or change button positions until the actual drop

            Prior Art

            • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
            • @dnd-kit/solid package -- already in the dependency tree
            • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

            Source

            Part of #684
            Blocked by #687
            Blocked by #688

            Metadata

            Metadata

            Labels

            afkImplementable without human interactionenhancementNew feature or request

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              feat(app): drag-and-drop reorder across titlebar slots #689

              Description

              @jeonghun-jj-lee

              Important

              Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

              Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

              Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

              Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

              Acceptance Criteria

              • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
              • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
              • Dragging a control within the right slot reorders it among right-slot controls
              • Dragging a control within the left slot reorders it among left-slot controls
              • Dragging a control past the tab strip's left edge moves it to the left slot
              • Dragging a control past the tab strip's right edge moves it to the right slot
              • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
              • On drop, the titlebarLayout setting is updated immediately
              • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
              • Dropping a control in the same position (no-op drag) does not trigger a settings write
              • Outside edit mode, no DnD context is active and controls are not draggable

              Testing Decisions

              Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

              Key Decisions

              • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
              • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
              • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

              Constraints & Invariants

              • The DnD context is only active during edit mode -- never outside it
              • left.concat(right) must still contain exactly the five canonical IDs after every drop
              • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
              • Drop indicators must not shift the layout or change button positions until the actual drop

              Prior Art

              • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
              • @dnd-kit/solid package -- already in the dependency tree
              • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

              Source

              Part of #684
              Blocked by #687
              Blocked by #688

              Metadata

              Metadata

              Labels

              afkImplementable without human interactionenhancementNew feature or request

              Type

              No type

              Projects

              No projects

                Milestone

                No milestone

                Relationships

                None yet

                Development

                No branches or pull requests

                Issue actions

                , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                Skip to content

                feat(app): drag-and-drop reorder across titlebar slots #689

                Description

                @jeonghun-jj-lee

                Important

                Problem -- Edit mode lights up the titlebar controls visually, but buttons cannot yet be dragged to new positions. The feature needs drag-and-drop reordering within slots and across the tab strip boundary.

                Approach -- Add a @dnd-kit/solid DnD context that wraps the titlebar during edit mode, separate from the tab strip's existing DnD context. Each of the five controls becomes a draggable item. Within a slot, standard sortable reorder applies. When a drag crosses the tab strip boundary (past the left edge of the tab strip for right-to-left, past the right edge for left-to-right), the button jumps to the other slot. Config saves on every successful drop.

                Scope -- in: DnD context wrapping both slots, within-slot sortable reorder, cross-slot boundary detection, drop indicators (thin vertical lines), save-on-drop to titlebarLayout setting. out: keyboard reorder (future accessibility enhancement).

                Assumptions -- Edit mode (slice 3) is active and the edit signal is readable. Two-slot rendering (slice 2) is in place with per-button mount points. The titlebarLayout setting (slice 1) is writable.

                Acceptance Criteria

                • A @dnd-kit/solid DnD context wraps the titlebar controls during edit mode, separate from the tab strip's DnD context
                • In edit mode, each of the five controls is draggable (cursor changes to grab/grabbing)
                • Dragging a control within the right slot reorders it among right-slot controls
                • Dragging a control within the left slot reorders it among left-slot controls
                • Dragging a control past the tab strip's left edge moves it to the left slot
                • Dragging a control past the tab strip's right edge moves it to the right slot
                • Drop indicators (thin vertical lines, accent color) appear between valid drop positions during drag
                • On drop, the titlebarLayout setting is updated immediately
                • The DnD context does not interfere with the tab strip's existing drag-and-drop (tab reorder continues to work)
                • Dropping a control in the same position (no-op drag) does not trigger a settings write
                • Outside edit mode, no DnD context is active and controls are not draggable

                Testing Decisions

                Extend the titlebar test surface. Test within-slot reorder (drag button A past button B, verify config order changes). Test cross-slot move (drag from right past tab strip boundary, verify button appears in left config array). Test DnD isolation (tab strip drag still works during edit mode). Test save-on-drop (config writes after each drop, not batched).

                Key Decisions

                • Separate DnD context from tab strip: edit-mode button DnD and tab-strip DnD are independent DndContext instances. No shared collision detection.
                • closestCenter collision strategy with custom boundary logic for cross-slot detection: the tab strip's midpoint is the threshold for deciding which slot the drop targets.
                • Save on every drop: no undo, no cancel. The config is always the source of truth. This means Escape is "exit edit mode" not "discard changes."

                Constraints & Invariants

                • The DnD context is only active during edit mode -- never outside it
                • left.concat(right) must still contain exactly the five canonical IDs after every drop
                • The tab strip's own DnD (tab reorder) must not break when the edit-mode DnD context is active
                • Drop indicators must not shift the layout or change button positions until the actual drop

                Prior Art

                • titlebar-tab-strip.tsx -- existing @dnd-kit/solid DnD setup for tab reorder
                • @dnd-kit/solid package -- already in the dependency tree
                • titlebar-tab-order.ts -- mergeVisibleTabOrder for reconciling drag reorder

                Source

                Part of #684
                Blocked by #687
                Blocked by #688

                Metadata

                Metadata

                Labels

                afkImplementable without human interactionenhancementNew feature or request

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions