Add proposal for modifying split views#1019
Conversation
Co-authored-by: Dave Vandyke <kzar@kzar.co.uk>
|
|
||
| #### tabs.createSplitView() | ||
|
|
||
| Requires a pair of tabIds referring to distinct tabs, rejects otherwise. |
There was a problem hiding this comment.
When I « Add Split View » in my browser (firefox or chromium), I have only only tab. The other one is an empty tab (about:opentabs in firefox). Is it possible to have the same behaviour if I pass only one tabId?
And what appends if I pass 3 or more tabs?
There was a problem hiding this comment.
When I « Add Split View » in my browser (firefox or chromium), I have only only tab. The other one is an empty tab (
about:opentabsin firefox). Is it possible to have the same behaviour if I pass only onetabId?
With the existing tabs.create API with the new splitWithTabId option, described above. Reason for relying on that method is to avoid duplicating the "create new tab" functionality.
And what appends if I pass 3 or more tabs?
Error, because we cannot create a split view with more than 2 tabs right now.
|
@Rob--W considering your concern about future-proofing the API, would it make sense to allow |
With the number of tabs in a split view being limited to 2, adding a tab to a split view automatically implies kicking another tab out of it. The mechanisms by which that should happen are not obvious (should tabs move around? Which one should be kicked out? etc). It may be possible to define something meaningful for limited scenarios, e.g. tabs already adjacent to each other. But then we'd basically duplicate the functionality of |
rdcronin
left a comment
There was a problem hiding this comment.
Thanks, Rob! Excited to see this!
|
|
||
| - Creating a split view from an existing tab, which creates a new split view | ||
| consisting of the specified tab, plus a browser-native UI page where the user | ||
| can choose the tab to adopt in that split. |
There was a problem hiding this comment.
the browser-native UI page here is unique to Firefox, I think (or at least, we don't have this in Chrome). Is this something we should include here?
There was a problem hiding this comment.
By "browser-native UI page" I meant a page potentially different from the default new tab.
In Firefox it is "about:opentabs", in Chrome is is chrome://new-tab-page/ (internally "chrome://tab-search.top-chrome/split_new_tab_page.html", opened at
https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/browser_commands.cc;l=1608-1612;drc=c9ae8a85e83fc4c4cb5531945ade924b940a816f ). If you want to see for yourself, open the context menu on a tab and use the "Add tab to new split view." option.
|
|
||
| - Separating split views. | ||
|
|
||
| - Reversing tabs in a split view. |
There was a problem hiding this comment.
| - Reversing tabs in a split view. | |
| - Reversing the order of tabs in a split view. |
| ```javascript | ||
| browser.tabs.create({ | ||
| // ... existing properties, including: url, index, active | ||
| splitWithTabId: number, // Existing tab to pair with |
There was a problem hiding this comment.
bikeshed: We could also call this "splitWith", since tabId is more of the type rather than the name of the value. And its shorter. But splitWithTabId does align more with openerTabId. Thoughts? (I don't feel strongly.)
There was a problem hiding this comment.
If the type is the same I prefer splitWithTabId, as it is also consistent with openerTabId like you said.
I initially considered (and actually started with) an object type, e.g. splitWith: { tabId }, but ultimately flattened that to minimize complexity in tabs.create.
E.g. one of the options I considered for the splitWith option was the relative placement, but I dropped that in favor of reusing the existing index property.
| splitWithTabId: number, // Existing tab to pair with | ||
| }) : Promise<Tab> // Returns new tab in split with given tab | ||
|
|
||
| browser.tabs.createSplitView( |
There was a problem hiding this comment.
createSplitView() is so long.
My instinct here is to actually just go with chrome.tabs.split(). This has good consistency with e.g. chrome.tabs.group(). That said, I know that it might also sound confusing (like you're "splitting" a single tab in half or something.)
Could also be createSplit()?
Again, I don't feel super strongly here, but it does kinda stand out as a long / clunky name compared to some others.
There was a problem hiding this comment.
createSplitView() is so long.
My instinct here is to actually just go with chrome.tabs.split(). This has good consistency with e.g. chrome.tabs.group(). That said, I know that it might also sound confusing (like you're "splitting" a single tab in half or something.)
At the design phase my mind went through all that you wrote here :)
I started with split() and unsplit(), but decided against "split" because it sounds like the tab would be split in pieces.
Could also be createSplit()?
I'm not fully opposed to it, but given that the ID is called splitViewId I prefer to be consistent and use "splitView" as the word, so "createSplitView".
For tabs.create, I nevertheless went with "splitWithTabId" because "splitViewWithTabId" was a mouthful and could too easily be confused with "splitViewId".
| tabIds: Array<number> // Two tabIds. | ||
| ) : Promise<number> // Returns splitViewId | ||
|
|
||
| browser.tabs.separateSplitView(splitViewId) : Promise<void> |
There was a problem hiding this comment.
and chrome.tabs.unsplit() : )
(or "removeSplit()". But I kinda like just "split()" and "unsplit()")
There was a problem hiding this comment.
I like unsplit, which was my first choice, but dropped it because "split()" was not a good option in my opinion.
I don't like "removeSplit" because it is ambiguous and can be mistaken for removing the split view and all of its tabs.
I went with "separate" because that is unambiguous and already the verb that Chrome and Firefox use in split view context menus.
| First, validate the options and ensure that it would create a tab next to the | ||
| tab specified by `splitWithTabId`. The method SHOULD reject if it cannot create | ||
| a split view (see createSplitView). If a tab was created, the created tab must | ||
| be returned as usual, even if the split view cannot be created. |
There was a problem hiding this comment.
Is the expectation then that the developer check splitViewId to see if the split view was actually created?
This sounds like something that would be very easy to get wrong. Do we need to support this case? Or should we instead say that it's a bug if the browser create a tab that was supposed to be split and then didn't split it?
There was a problem hiding this comment.
Is the expectation then that the developer check splitViewId to see if the split view was actually created?
The expectation is that we reject with an error if a split view cannot be created, expressed as "SHOULD". Since "SHOULD" is not a "MUST", I decided to also specify what the (reasonable) behavior is. tabs.create's primary purpose is to create a tab, and if it creates a tab it should return it, to prevent "leaking" tabs that the extension does not know about. Naturally, if the split view failed to create, then its splitViewId should be -1.
This sounds like something that would be very easy to get wrong. Do we need to support this case? Or should we instead say that it's a bug if the browser create a tab that was supposed to be split and then didn't split it?
I am willing to turn the SHOULD into a MUST, in which case the situation does not occur. This imposes higher requirements om the browser implementers, which I'd be fine with, if you are too.
|
|
||
| ### Behavior | ||
|
|
||
| #### tabs.create() with splitWithTabId option |
There was a problem hiding this comment.
kind of obvious, but we should also say that it has to be in the window with the tab it's being split with.
There was a problem hiding this comment.
That is already covered by:
if it cannot create
a split view (see createSplitView).
And in createSplitView one of the failure conditions is:
mismatching "windowId" states
| `tabs.onUpdated` events. | ||
|
|
||
| When tabs are not adjacent, or even in order, the implementation MAY try to | ||
| move the tabs to the given order and join them. |
There was a problem hiding this comment.
it seems like this is something we should specify more than "MAY". Should we move, or should we not?
My $0.02: I don't think we should reorder / move them.
- We don't allow tabs that aren't in the same window (or other conditions, as above), so to create a new split, an extension may already need to do some tab management.
- It seems a bit arbitrary to assume the extension wants to do this move, but not make the same assumption that it would want to e.g. change the pin state, etc. And making all those assumptions is a lot of assumptions.
- Bundling these operations increases the likelihood that the function "half works" -- for instance, it might move the tabs, but not create the split view, violating the "don't change the state if it didn't succeed" bit below.
- In theory, browsers may not require splits to be next to each other in the future (why should they need to be?). Preemptively moving these means that if we changed that in the future, it causes significant behavior changes for extensions.
- We could potentially change this behavior in the future to allow the case of moving tabs for the split. We can't go the other direction and stop allowing it.
There was a problem hiding this comment.
I'm onboard with rejecting if they are not adjacent. We can always relax later, which I could call out in the future work section.
| request of moving a split view. | ||
|
|
||
| If the `index` behavior of `tabs.move` weighs more strongly, then the move of | ||
| tabs MAY separate tabs automatically. |
There was a problem hiding this comment.
MAY here also seems underspecified.
What do each of the browsers do today? If we already have consistent behavior, is it worth specifying? (If we don't, then MAY is fine)
There was a problem hiding this comment.
Chrome separates the split, and I don't know if there were much thoughts behind this behavior.
Firefox tightly keeps tabs in a split view together, treating then as one unit unless there are clear indicators that they should not be together. The unity of split views was a Product requirement, and followed from the experience with tab groups, where users were surprised that the tab groups they created were ungrouped. Turns out that there was an extension that was unaware of tab groups and as part of reshuffling, the tabs were taken out of a tab group.
I documented the options (Chrome vs Firefox) along with the decision and expected behaviors for tabs.move at https://bugzilla.mozilla.org/show_bug.cgi?id=2016751
There was a problem hiding this comment.
@rdcronin Is Chrome willing to adopt Firefox's behavior, where tabs in a split view move together by default?
A Chrome extension developer expressed their preference for Firefox's behavior (as part of a larger comment describing their use case, at #967 (comment))
From a consumer's perspective, the most valuable guarantee would be that the "move as a unit" behavior is at least available and discoverable (vs. Chrome's current always-unsplit), so extensions don't have to detect the unsplit after the fact and stitch the split back together.
|
+1 on this proposal — thanks for putting it together, @Rob--W. I left a detailed real-world use case over at #967 (comment): a Chromium side-panel tab manager that currently has to block drag-reordering of individual split-view tabs because |
Proposal for: