Re: [w3ctag/design-reviews] EyeDropper API (#587)

First, there is a need for this in the developer community and I'm happy to see this work. However, I see a number of issues with the API in its current form.

### Hex colors are in sRGB, which cannot represent all on-screen colors

The most serious issue I see with this proposal is that the API returns hex colors, which [on the Web platform are in sRGB](https://www.w3.org/TR/css-color/#hex-notation). What this means is that the CSS color `#ff0000` is not the brightest red the screen can produce, it's sRGB red, which is typically far less saturated than device RGB red for most modern screens (e.g. for a P3 screen, like most modern Apple devices, it would be equivalent to device [91.8% red, 20% green, 13.9% blue](https://colorjs.io/notebook/?storage=https%3A%2F%2Fgist.github.com%2FLeaVerou%2F4ab436b39a67db3dbfe1ea291f9a9679)). This proposal seems to suggest returning a hex encoding of device RGB coordinates. We are trying to avoid exposing device RGB on the Web platform these days, as there is no way to ensure consistent results. This means that, as currently defined, **this API will return colors that are not actually the color picked in any Web platform technology, defeating the purpose of an eyedropper**. Furthermore, there is not even a way to convert them to the color the user actually selected.

I'm not sure what is the best way to deal with this, since none of the currently widely supported color formats can express all on-screen colors. Ideally, the API should return one of the [CSS supported device independent color formats](https://www.w3.org/TR/css-color-4/#lab-colors), such as `lab()` or `lch()` but support is currently limited. One may suggest returning hex when the color is within sRGB and another format when it is not, akin to [computed values](https://www.w3.org/TR/css-color-4/#resolving-color-values). However, not only is this inconsistent and would cause developer pain when parsing the value, but the cases where on-screen colors fall outside sRGB are not exactly rare: in modern P3 screens, [33% of colors are outside sRGB](https://twitter.com/svgeesus/status/1220029106248716288) and thus, cannot be specified with hex colors. 

### Eyedropper starting point

Given the way the API is currently defined, there is no way to specify the starting point for the eyedropper, which would be jarring for end users. Typically, in most UIs of that sort, the eye dropper starts from the location of the user interaction (where applicable), e.g. see on OSX:

https://user-images.githubusercontent.com/175836/104420064-53173180-5547-11eb-888d-893d7c304837.mp4

### Event Design

It is unclear to me why `eyeDropper.open()` is asynchronous with the current design, since color selection happens via the `colorselect` event, and not via a promise. It does not appear to tick any of the criteria for an asynchronous operation ([see TAG Design Principle 5.7](https://w3ctag.github.io/design-principles/#synchronous)).

However, stepping back from the details for a moment, it appears that a lot of the complexity here has to do with using an event-based model, which has been chosen to enable selection of multiple colors. However, I am missing a list of use cases that require such multiple color selection. In most cases of eyedropper UI in the wild that I have come across, the eyedropper typically closes after color selection, which also serves as useful *[feedback](https://www.nngroup.com/articles/ten-usability-heuristics/#articleBody:~:text=appropriate-,feedback)* to the end user that their selection has been accepted. If the eyedropper did not close, it is difficult to communicate to the user that their selection has been recorded, or display what their selection was, not to mention that it would be externally inconsistent with most other eyedropper interfaces. If such use cases exist for multiple selection, one could always re-open the picker after selection of the first color, since there is arbitrary open/close functionality. The spec could ensure that calling `open()` right after the eyedropper closes is seamless. Prioritizing the single selection common case also means that developers don't need to explicitly call `close()` to close the picker every time (which I can see causing many confusing bugs, e.g. when an error is thrown before the call to `close()`, so the picker is left open).

Playing around with these ideas, the code sample listed in the explainer could look like this with a promise-based design and ability to specify start coordinates:

```js
// Create an EyeDropper object
let eyeDropper = new EyeDropper();

// Enter eyedropper mode
let icon = document.getElementbyId("eyeDropperIcon")
icon.addEventListener('click', async e => {
    let selection = await eyeDropper.open({left: e.clientX, top: e.clientY});
    // if we are here, the picker has closed, either by selection, or via the user choosing to exit
    // we can call eyeDropper.open() to re-open it, or do work with selection

    if (selection.color !== null) { // a color was selected
        console.log(selection.color); // logs selected color

        if (selection.position !== null) { 
            // The selected pixel came from our own document (or a document of same origin)
            // The selected pixel is located at:
            console.log(`${selection.position.left}, ${selection.position.top}`)
        }
    }
});
```

Please note that this is just a quick sketch to make the feedback above more concrete, and not necessarily the way you should go!

### Containing color selection

> This proposal does not currently define a mechanism to allow developers to hide or show the eyedropper's pixel selection UI while remaining in eyedropoper mode, but a future version may allow that, for example, to facilitate clicking on application UI elements instead of selecting a color value.

Note that to replicate the UIs that *do* support multiple color selection with an eyedropper, merely preventing the eyedropper from closing or re-opening it does not suffice. These UIs typically *exclude* an area of the screen from selection, and this area contains some of the color-related UI and provides feedback for the color selection. Take a look at this capture from Adobe Photoshop:

https://user-images.githubusercontent.com/175836/104432201-c4aaac00-5556-11eb-86f8-52d2e5652686.mp4

Note that the actual color picker dialog does not participate in the eyedropping.

Furthermore, authors may want to contain the selection within their application, or even a part of their application (e.g. the Photoshop picker does not select colors outside of the Photoshop window).

If you want to replicate these interactions on the Web, it may be worth exploring ways to specify elements to exclude, and/or contain the selection within the viewport or specific elements.

-------

Btw

> This proposal does not currently define an object model for a color, though it seems like something that would be a good addition to the web platform.

There is [some](https://github.com/w3c/css-houdini-drafts/issues/989#issuecomment-667228353) work on that.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3ctag/design-reviews/issues/587#issuecomment-759339846

Received on Wednesday, 13 January 2021 09:59:10 UTC