[w3c/manifest] More precise control over app window features (#856)

This is an umbrella issue that keeps coming up over and over over the past few years. It's been discussed in small pockets but I don't think there is a dedicated Manifest issue tracking it, so here is one.

## The problem

Broadly speaking, the problem is this: `display` mode and its associated fallback chain does not give developers enough control over the app window, and it's too inflexible to allow us to build new features on top of. This has manifested in a number of separate issues:

1. When we want to add a new feature, that "looks like" a new display mode, it's unclear how to fit it into the fallback chain. This came up for tabbed application mode (#737) in 2018 (still WIP), and now title bar customization (MicrosoftEdge/MSEdgeExplainers#206). By adding new display modes for new features, it's impossible for sites to mix and match these features.
2. Each display mode is poorly specified and inconsistent across implementations (#673). Developers have no guarantee about what controls they're actually going to get. It's nice in theory to give control over window UI to the user agent, but in practice, it means developers will build with the most popular browser in mind and create de facto standards (for example, if popular browsers add a back button to `display: standalone`, sites will assume it exists). Because of this, we've needed (and have not yet succeeded) to provide ways to query whether these controls are being provided by the user agent (#693).
3. The fallback chain is inflexible. Some sites may want `minimal-ui` falling back to a browser tab. But other sites may only have a slight preference for minimal UI, and be happy to fall "up" to `standalone` if the user agent doesn't support minimal.

On the first issue, a very similar discussion happened in #737 and MicrosoftEdge/MSEdgeExplainers#206. Do we add the new display mode and slot it into the linear fallback chain (e.g., between `fullscreen` and `standalone`?) Or do we break the linearity of the fallback chain, so `fullscreen` still falls back to `standalone` whilst `my_new_feature` also falls back to `standalone`? Or do we add the new feature as a separate Boolean member alongside `display`?

Having `fullscreen` fall back to tabbed mode, or even title bar customization mode, is very problematic, since both of those modes are somewhat special and really should require explicit opt-in from developers. The non-linear fallback chain solves this, but it means you can't mix and match (for example, there would be no way to have a tabbed application with a customizable title bar).

On the third issue, I believe (maybe I'm wrong) that Chrome just recently became the first major browser to actually support the long-time-specced `display: minimal-ui`. Historically, `minimal-ui` has basically been equivalent to `browser`. Encouraging devs to adopt `minimal-ui` now that it's launched in Chrome is difficult, since you're basically foregoing "being a PWA" in other browsers that don't support this mode.

## Proposed solutions

Several solutions have been proposed. I'll try to aggregate them here.

### Add new features as separate members

This is the most straightforward. We keep the existing display modes, but don't add any new ones. All new features are "add-ons" which have their own member. For example:

```json
{
  "display": "standalone",
  "tabbed_mode": true,
  "caption_controls_overlay": true
}
```

This solves issue 1, but not 2 or 3, and could result in a lot of new top-level members.

### Allow sites to specify an explicit fallback chain

Something that @dmurph proposed in a private chat with me this morning. Allow `display` to be either a string or a list of strings; the new list form allows developers to explicitly specify their fallback chain. So now, I can have `"display": "minimal-ui"` if I want minimal, falling back to browser, or `"display": ["minimal-ui", "standalone"]` if I have a slight preference for minimal, but definitely want some form of standalone window.

My suggestion was that new features can *only* be specified in the list form, and the list *must* include at least one of the four legacy modes. So `"display": "tabbed"` would be illegal, as would `"display": "tabbed"`, but you could have `"display": ["tabbed", "standalone"]` (if you want tabs in your app window but don't mind if it's not supported, or `"display": ["tabbed", "browser"]` (if you absolutely must have a tabbed UI, and if not supported, let the user use their browser tabs).

This partially solves issue 1 (but doesn't allow mixing and matching new features), and solves issue 3, but not 2.

### Media query for individual elements like back button

Proposed by me in #693 and explainer written by @fallaciousreasoning [here](https://github.com/fallaciousreasoning/backbutton-mediaquery). This doesn't outright solve any of the above issues, but at least gives developers a way to detect which elements are being shown to the user, partially solving #2 above.

This solution is probably necessary in addition to other measures, in order to feature detect browsers that have / have not implemented other measures.

### Add a `display-modifiers` member

This was proposed by @aarongustafson on [MicrosoftEdge/MSEdgeExplainers#206](https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/206#issuecomment-592138391). Keep the existing `display-mode`, but add a new dictionary member, `display-modifiers`, which lets developers add or remove things piecemeal.

He proposed the new title bar customization feature as simply a "removal" of the `"titlebar"` feature:

```json
{
  "display": "standalone",
  "display_modifiers": {
    "titlebar": false
  }
}
```

But this also allows you to explicitly add or remove individual elements like back button, refresh button, etc. I think these would still have to be hints to the UA (we can't mandate that the UA show a refresh button, for instance), but they could be SHOULD requirements.

This would solve 1 because you could choose any of the four existing display modes (or at least choose between `standalone` and `minimal-ui`, and then add or remove new features).

This would partially solve 2, because even though `display` would still be poorly specified (and up to UAs which features they imply), the developer could precisely ask to have, or not have, the things they care about.

This would solve 3 because you can essentially make your own fallback chain. If you want minimal UI but if unsupported, fall back to a standalone window, then you should do `display: standalone` with a bunch of modifiers to make a bespoke `minimal-ui`.

I like this solution. One nice thing about it is that it's backwards compatible: browsers that don't implement `display_modifiers` will still make a best effort to give you what you asked for.

I've proposed a similar solution before (can't find a source), but my solution has a slightly different slant: instead of display "modifiers", we design as if `display` didn't exist: create a new bag of `window_controls` (or whatever), which defines all the windowing properties, and then respecify `display` as simply a preset setting for `window_controls`. This would fully solve problem 2, because now `display` is precisely specified (and while it would still be up to the UA how to interpret each individual window control, it would at least finally be clear what developers are asking for when they say `display: standalone` or `display: minimal-ui`.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/manifest/issues/856

Received on Friday, 27 March 2020 03:21:35 UTC