Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a "tabbed application" mode #737

Open
mgiuca opened this issue Nov 12, 2018 · 32 comments
Open

Add a "tabbed application" mode #737

mgiuca opened this issue Nov 12, 2018 · 32 comments
Assignees
Labels

Comments

@mgiuca
Copy link
Collaborator

mgiuca commented Nov 12, 2018

A feature request to add a "tabbed" mode for installed applications. This would be similar to "standalone" in that when the application is installed, it can be opened in a separate window dedicated to that application. However, in "tabbed" mode, the user agent would divide the window into tabs, similar to a tabbed web browser, except that all the tabs belong to the app (and don't have a URL bar).

Differences to a normal web browser window:

  • The window has the title and icon of the app, not the web browser.
  • There could be a "new tab" button, but it would open a page at the application's start_url.
  • Like a standalone window, browser-specific features like a URL bar, navigation buttons, etc, may be hidden.

(At the user agent's discretion), the user would be able to drag tabs around, split them out to separate application windows, drag tabs in the application scope between app windows and regular browser windows.

Essentially this lets web developers easily build multi-document interfaces for productivity applications.

Why not just let developers build their own tabbed interface in HTML?

This could be made into a library, where you embed your document pages inside an iframe. However, it would have a number of drawbacks compared to a user agent implementation:

  • The tabs could not be dragged out of the window to split into a separate application window, or dragged back in to combine into a single window.
  • The tabs could not be dragged to a regular browser window to transfer them back to a normal browsing context.
  • The tabs could not be dragged from a browser window into the application.
  • User agent affordances such as "copy this page URL", "cast this tab" or "open this page in a web browser" would be applied to the tabbed interface page, not the currently selected document page.

Why can't a user agent just interpret "display: browser" as this tabbed mode?

(i.e., why do we need to spec this at all?)

Because display: browser already has a specific meaning. "Opens the web application using the platform-specific convention for opening hyperlinks in the user agent (e.g., in a browser tab or a new window)." While user agents can do whatever they want regarding UI, it would clearly be a pretty big subversion of developer expectations if "display: browser" suddenly meant "run in a separate application-specific window with no browser affordances, but a tabbed document interface".

"display: browser" is the way you opt out of being put into an application window.

Furthermore, "display: browser" is at the bottom of the fallback chain. If a user agent doesn't support, say, "display: minimal-ui", it is required to fall back to "display: browser". It doesn't make sense that a developer requesting "standalone" would get a standalone single-document window with no browser UI, while a developer requesting "minimal-ui" (i.e. asking for more browser UI) would get a standalone multi-document window with no browser UI.

User agents SHOULD NOT treat "display: browser" as a tabbed document application window.

How should this be requested, then?

The obvious answer is to add a new display mode: "display: tabbed" or "display: multidoc" (the latter would let user agents provide a different multi-document interface, in case there is a Windows 95 implementation 😄).

One potential issue is that it doesn't fit cleanly into the fallback hierarchy. Currently, the fallback hierarchy is: fullscreen > standalone > minimal-ui > browser. If we put "tabbed" above "standalone", then that implies a user agent that doesn't support "fullscreen" should fall back to "tabbed" (bad). If we put it above "fullscreen", then that implies a user agent that doesn't support "tabbed" should fall back to "fullscreen" (also bad).

We could make the fallback hierarchy a DAG, which would look like this:

   tabbed
          \
           > standalone > minimal-ui > browser
          /
fullscreen

I think that would be reasonable, however it precludes the possibility of a "tabbed, miminal-ui" mode.

The other approach is that we make "tabbed_mode" or "multidoc_mode" a separate member that you can enable, in tandem with "display: standalone" or "display: minimal-ui" which would resolve the above issue.

@mgiuca mgiuca self-assigned this Nov 12, 2018
@kenchris
Copy link
Collaborator

kenchris commented Nov 19, 2018

If you drag a tab out, and say into a browser, then it will change display-mode I assume? That will affect whether it makes sense to have these as separate members or not

@mgiuca
Copy link
Collaborator Author

mgiuca commented Nov 20, 2018

I would think so. Yeah I'd want you to be able to detect whether it's in a tabbed mode (so you could implement your own tabbed interface in HTML and disable it if you're in a tabbed mode). So however we do it, I'd want to make it detectable. It seems that decoupling it from display-mode would mean we have to add more media features. So perhaps using display-mode is the easiest here.

@evanw
Copy link

evanw commented Mar 12, 2019

Another reason for "Why not just let developers build their own tabbed interface in HTML?": it enables developers to create multiple child tab processes for stability, parallelism, and security isolation.

I work at Figma, an in-browser design tool, and I've been looking at using potentially making a web app manifest alternative to our Electron-based native app (which has a tabbed UI). We are unable to build a tabbed interface in HTML because each tab of ours often uses 1gb+ of memory and users often have 10+ tabs open. A HTML-based tab interface with iframes would trigger the browser's OOM killer and crash the tab. It would also run all tabs on the same thread which would be very bad for performance. We're using Electron's BrowserView API instead of iframes to accomplish this in Electron but there's currently no way to accomplish this with web APIs.

@voxpelli
Copy link

I would love to have something like this in the newspaper PWA we're creating at work and I would certainly push for something like this there whenever it arrives.

I myself usually read news sites in the browser rather than in an app as I then can open new articles as I scroll by them in a list and then go back and forth until I have read all of the tabs and are done for the day.

Being able to utilize the power of browsers and having it as an option in a PWA could finally enable doing that in an easy manor.

@alancutter
Copy link
Contributor

Assuming tabbed PWAs happen would you want more control over the tabs than is currently available with browser tabs?

@voxpelli
Copy link

I would prefer it if I could control the tabs UI and have those tabs only be tabs that are owned by the PWA, leaving external content opened as it is today in a PWA

Then the PWA would continue to be fully styled by itself, just like a native app.

@alancutter
Copy link
Contributor

external content opened as it is today in a PWA

In Chrome today it shows a bar indicating you've gone off scope. Is that what you had in mind?
Screenshot from 2019-08-26 17-00-58

@voxpelli
Copy link

@alancutter Yes, as for security reasons it would not be possible to allow for those to be included in a tabbed UI styled and controlled by the PWA itself, as it could then easily masquerade as showing a site that it isn’t

@AndersFriborg
Copy link

Tabs in PWA is a really good feature. Is there any information on the progress of this? @mgiuca?

@mgiuca
Copy link
Collaborator Author

mgiuca commented Feb 9, 2020

Thanks for asking. There isn't any updates on the spec side, but @alancutter is prototyping it behind a flag in Chrome. I believe it should be usable in Canary/Dev channel behind a flag soon. One of us will post an update here when it is.

@AndersFriborg
Copy link

Ok thanks for the update @mgiuca and keep up the prototyping @alancutter :-)

@vjpr
Copy link

vjpr commented Apr 6, 2020

@alancutter Is there anyway to try out desktop PWA tab strips in Chrome? What does the flag chrome://flags/#enable-desktop-pwas-tab-strip currently do? Looks like its only ChromeOS at the moment.

Would love to see this on macOS. E.g. When running productivity apps as bookmarked apps, I would like to be able to open documents as tabs in the same window.

@alancutter
Copy link
Contributor

Currently this experimental implementation is only functional on Chrome OS 83+, the flag enables you to change the launch mode to be a tabbed window.

@tomayac
Copy link
Contributor

tomayac commented Feb 16, 2021

I played with the Chrome OS implementation and noticed that all storage seems to be shared between all tabs. For example, if an app keeps state in localStorage, all tabs share the same state. The Windows 95 implementation you jokingly linked to in the original thread has a dedicated section on child window data, which lists two ways of storing data, for example, the name of the current file:

  • Store child window data in the window structure.
  • Use window properties.

Will there be a platform way to do this, or are implementations expected to manage tab state themselves (and if so, what do you propose to re-identify the same tab)?

@tomayac
Copy link
Contributor

tomayac commented Feb 16, 2021

How does this interact with display_override? The "tabbed" value should probably be an allowed value of display_override rather than be fitted into the fallback chain of display.

@kenchris
Copy link
Collaborator

How does this interact with display_override? The "tabbed" value should probably be an allowed value of display_override rather than be fitted into the fallback chain of display.

I believe this was the plan. At least that is what I have heard before and it was discussed as part of display_override

@kenchris
Copy link
Collaborator

and if so, what do you propose to re-identify the same tab

From service workers you can get access to clients (this is why the sw-launch event is so powerful and flexible, as you can find a particular window and focus it etc), so maybe a similar API could be exposed when running in tabbed mode?

@kenchris
Copy link
Collaborator

kenchris commented Feb 18, 2021

For getting everything to work like media query and existing implementations, we should add tabbed to DisplayModeType and define 'display' fallback as 'browser'. That is compatible with what we have today and will make it work in the media query.

If people want to define their own fallback order they can use display_override and that is what we should recommend.

Like setting

"display_override": ["tabbed", "standalone"],
"display": "standalone"

meaning fallback will be (manual: tabbed -> standalone) -> (automatic: standalone -> minimal-ui -> browser).

I am here assuming that if none of the values in display_override are know or supported, it will fall further back to the original display which makes the most sense (I hope that is how display_override is defined)

If you just set

"display": "tabbed"

It should work on supported browsers but fallback will be "browser" - that is compatible with what happens today.

It might even be fine defining a different fallback (as it is a fallback anyway) like what Matt originally suggested

tabbed -> standalone -> minimal-ui -> browser.

That would mean that "display": "tabbed" would have the same fallback as

"display_override": ["tabbed", "standalone"],
"display": "standalone"

as "display": "standalone" falls back to -> minimal-ui -> browser

@alancutter
Copy link
Contributor

alancutter commented Feb 22, 2021

I played with the Chrome OS implementation and noticed that all storage seems to be shared between all tabs. For example, if an app keeps state in localStorage, all tabs share the same state.

For tab scoped storage you can store things on globalThis.

@tomayac
Copy link
Contributor

tomayac commented Feb 22, 2021

For tab scoped storage you can store things on globalThis.

Thanks for the reply. Session storage would be another (probably preferable) alternative.

What I was after was storage that is persisted across sessions, though. To make this clearer: The user edits document data in PWA tab 1 and PWA tab 2 and wishes to persist both locally in the browser, but not in a file. Right now, the user could namespace localStorage per PWA tab, but ideally there'd be a platform way to do this.

I guess the question also includes whether developers are to think of PWA tabs conceptionally different than of regular browser tabs.

@alancutter
Copy link
Contributor

alancutter commented Feb 23, 2021

Sounds like: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

Edit: Sorry you already mentioned that, you mean for it to persist. When would it expire?

@tomayac
Copy link
Contributor

tomayac commented Feb 23, 2021

Sounds like: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

Edit: Sorry you already mentioned that, you mean for it to persist. When would it expire?

“Never” as in localStorage-never. In my ideal world each PWA tab would just magically create a tab-specific localStorage (and IDB) storage bucket. This would be different from regular tabs.

blueboxd pushed a commit to blueboxd/chromium-legacy that referenced this issue Jun 7, 2021
This change means the flag can be used in components/ and content/ in
https://chromium-review.googlesource.com/c/chromium/src/+/2929540.

w3c/manifest#737

Bug: 897314
Change-Id: I62bff44e6e5b94d0434cdb76ff33d23197cbb4ca
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2929417
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Alan Cutter <alancutter@chromium.org>
Reviewed-by: Dominick Ng <dominickn@chromium.org>
Commit-Queue: Louise Brett <loubrett@google.com>
Cr-Commit-Position: refs/heads/master@{#889631}
@thibPG
Copy link

thibPG commented Sep 15, 2021

With the current implementation, when in tabbed mode, the PWA right click menu has "open in new tab" but the active tab looses focus when doing this; Is it possible to have a behavior similar to regular browser window (use case: opening multiple document from a index page)

@tomayac
Copy link
Contributor

tomayac commented Apr 21, 2022

Noting that Tabbed Application Mode cannot be used together with Window Controls Overlay. Tracked as WICG/window-controls-overlay#55.

@mariusheine
Copy link

Is there any information about when it gets officially enabled/supported? We tested it under the experimental flags and it works great for us.

But every user must enable it by himself... That's why I am asking.

@tomayac
Copy link
Contributor

tomayac commented Apr 22, 2022

Is there any information about when it gets officially enabled/supported? We tested it under the experimental flags and it works great for us.

This is not a spec question, but an implementation question. Could you ask on the Chromium bug instead? Thanks.

@tomayac
Copy link
Contributor

tomayac commented May 17, 2022

Interlinking WICG/manifest-incubations#55 and the present Issue.

@wraiford
Copy link

Because display: browser already has a specific meaning. "Opens the web application using the platform-specific convention for opening hyperlinks in the user agent (e.g., in a browser tab or a new window)." While user agents can do whatever they want regarding UI, it would clearly be a pretty big subversion of developer expectations if "display: browser" suddenly meant "run in a separate application-specific window with no browser affordances, but a tabbed document interface".

This is entirely what does NOT happen on Chrome mobile (Android). With either display: "browser" or no display setting at all, Chrome mobile adds a link that looks like it's going to open the browser - but doesn't. It opens a single-tabbed application - exactly what the above quote says would be a "pretty big subversion". And he/she is correct in my particular case.

As such, it looks like I can't use the tabs in an offline manner for any PWAs at all. Firefox for Android does not respect the service worker properly and starts giving connection errors. And Chrome mobile does indeed work offline, but it only shows one tab without the ability to even open in the Chrome Mobile browser proper. I do see that the desktop does at least allow "Open in Chrome" which would totally be fine in the mobile if not slightly annoying. But a large difference between the desktop app is that it is easier to drag bookmarks to the desktop (screen), whereas this functionality exists on mobile only as the Add to Home Screen functionality. So I can't just add a bookmark to my Android's "desktop" home screen to even work around the lack of tab functionality.

It is my understanding that the "tabbed application" is only being currently implemented on the desktop. Is that correct? Could someone point me to an issue or where to create a new issue with the Chrome mobile PWA team to at least request the ability to "Open in Chrome" as a stop gap until tabbed functionality gets extended to mobile?

@EiraGe
Copy link

EiraGe commented Aug 16, 2022

With either display: "browser" or no display setting at all, Chrome mobile adds a link that looks like it's going to open the browser - but doesn't. It opens a single-tabbed application

I believe as for now, Chrome mobile allows only "add to homescreen" instead of "install" when display: "browser" or no display. Opening the added shortcut will open the url in a browser. Is the "a single-tabbed" you refer to sounds like the "minimal-ui" mode which opens a custom tab?

And Chrome mobile does indeed work offline, but it only shows one tab without the ability to even open in the Chrome Mobile browser proper.

Chrome mobile allows "Open in Chrome" too. It's not too obvious though. When the installed app is opened, there is a silent notification that gives the option to "Open in Chrome".

@wraiford
Copy link

Is the "a single-tabbed" you refer to sounds like the "minimal-ui" mode which opens a custom tab?

Hi @EiraGe I've tested many settings, including yesterday with the minimal-ui. Today I've only tested with standalone, fullscreen and browser (and none at all that goes to the default). Each time I check that the manifest.webmanifest is pulling correctly and I do everything I can to delete all cookies/site data. It correctly toggles back and forth between standalone, fullscreen and browser so I'm confident that caching is not the issue (IOW it's not from minimal-ui testing from yesterday). Rather, it simply does not open in the browser.

You're welcome to test it yourself at https://ibgib.space (with the manifest at https://ibgib.space/manifest.webmanifest not manifest.json). Just now I removed Chrome mobile PWA again, cleared cache (didn't restart but I have tried that, as well as clearing all data for the past 7 days since I usually use FF), went back to the site, "Add to Home screen", opened and there was no toast or notification, and there is no affordances outside of my app that would let me "Open in Chrome". I double-checked that the manifest.webmanifest is currently set without a display key at all, so it should have defaulted to browser. But I don't want to hijack this spec page on my troubleshooting! Unfortunately GH doesn't allow for tangents and I appreciate that this issue is for the spec. I'm just trying to influence the spec that A) Tabbed is of utmost importance, B) Mobile should be of utmost importance.

I thought perhaps someone has made changes on the mobile side that this issue wasn't aware of...but perhaps my triple+ checking was still incorrect and I've been missing something.

@mgiuca
Copy link
Collaborator Author

mgiuca commented Aug 17, 2022

@wraiford : Based on my understanding, Chrome on Android lets you add to homescreen and the result will be based on "display". If it's "display": "browser" (or nothing), it will just act like a normal browser shortcut, opening a new tab in the Chrome browser. If it's "display": "minimal-ui" or "standalone", it will create its own window. This seems aligned with the spec. I suspect you are installing an app with "display": "minimal-ui" or "standalone".

This is fairly orthogonal to what is being proposed here, which is a separate tabbed mode inside a standalone app window. (That is the point being made in the paragraph you quoted, which is to emphasise that "display": "browser" is not appropriate for triggering the standalone tabbed mode.)

It is my understanding that the "tabbed application" is only being currently implemented on the desktop. Is that correct?

That is currently correct for Chrome, though this GitHub is in the W3C which is browser-neutral, and I can't speak for other browsers. There is nothing stopping another browser (or Chrome in the future) from implementing standalone tabbed mode on mobile, though more UX research is probably required.

Could someone point me to an issue or where to create a new issue with the Chrome mobile PWA team to at least request the ability to "Open in Chrome" as a stop gap until tabbed functionality gets extended to mobile?

Again, this isn't a Chrome issue tracker so I don't want to get too far into discussing Chrome bugs here. You can always file a bug at https://crbug.new. I don't think having tabbed application mode on mobile will help what you want. (It would mean the apps you install are getting their own mini tab interface, and only if they request "display": "tabbed".) Sites with "display": "browser" should already be doing what you want. Sites with "display": "minimal-ui" or "standalone" should open in their own window, but as @EiraGe stated, there is a pull-down notification that lets you open them in Chrome. It sounds as though things are working as intended on the Chrome side.

@mgiuca
Copy link
Collaborator Author

mgiuca commented May 27, 2024

Following up this thread: tabbed app mode is incubating in the manifest-incubations repo. We have spec text in there.

Meanwhile, the feature is shipping in Chrome 126 (only on ChromeOS).

We'll keep this issue open here, as it hasn't landed in the Manifest repo (requiring a second implementation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests