Manifest: Add a "tabbed application" mode

Created on 13 Nov 2018  Â·  22Comments  Â·  Source: w3c/manifest

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 :smile:).

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.

Defer Feature Request

Most helpful comment

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.

All 22 comments

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

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.

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.

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.

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

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.

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

@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

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

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.

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

@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.

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.

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)?

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.

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

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?

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

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.

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.

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?

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.

Was this page helpful?
0 / 5 - 0 ratings