This document describes an API providing access to a browser supplied eyedropper.

Introduction

Currently on the web, creative application developers are unable to implement an eyedropper, a tool that allows users to select a color from the pixels on their screen, including the pixels rendered outside of the web page requesting the color data.

This API enables authors to use a browser supplied eyedropper in the construction of custom color pickers.

API Description

ColorSelectionResult dictionary

          dictionary ColorSelectionResult {
            DOMString sRGBHex;
          };
        
sRGBHex
must have a value that is a valid simple color

ColorSelectionOptions dictionary

          dictionary ColorSelectionOptions {
            AbortSignal signal;
          };
        
signal
allows to abort the {{EyeDropper/open}} operation.

EyeDropper interface

            [Exposed=Window, SecureContext]
            interface EyeDropper {
                constructor();
                Promise<ColorSelectionResult> open(optional ColorSelectionOptions options = {});
            };
        
open()
The method must follow these steps:
  1. If the [=relevant global object=] of [=this=] does not have [=transient activation=], return [=a new promise=] [=rejected=] with a "{{NotAllowedError}}" {{DOMException}}.
  2. If another eye dropper is already open then return [=a new promise=] [=rejected=] with an "{{InvalidStateError}}" {{DOMException}}.
  3. Let |result| be [=a new promise=].
  4. If options.signal is present, then perform the following sub-steps:
    1. If options.[=signal=] is aborted, then [=reject=] |result| with options.[=signal=]'s abort reason and return |result|.
    2. Add the following abort steps to options.[=signal=]:
      1. Exit "eyedropper mode" and dismiss UI.
      2. [=Reject=] |result| with options.[=signal=]'s abort reason.
  5. Place the web page into an "eyedropper mode" where user input is suppressed: no UI events are dispatched to the web page.
  6. [=In parallel=]:
    1. Let |colorSelectionResult| be the result of the user succesfully selecting a color. If this fails, then:
      1. If the user aborts the selection, [=reject=] |result| with an "{{AbortError}}" {{DOMException}}, otherwise [=reject=] |result| with an "{{OperationError}}" {{DOMException}}.
      2. Abort these steps.
    2. Exit "eyedropper mode" and dismiss UI.
    3. [=Resolve=] |result| with |colorSelectionResult|.
  7. Return |result|.

EyeDropper

To {{EyeDropper/open}} an eyedropper, the user agent MUST present a user interface that follows these rules:

Security and Privacy Considerations

Exposing endpoints allowing developers to access unrestricted pixel data from a user's machine presents security challenges. In particular any eyedropper implementation should not allow a web page to "screen scrape" information the user didn't intend to share with the web application, for example, while the user moves the mouse around the screen.

One way to mitigate this threat is to require that pixel data only be made available to the web application when the user takes some explicit action like pressing a mouse button.

Additionally, browsers should provide a clear indication as to when the user has been transitioned into an eyedropper mode, for example by changing the cursor, and provide the means for the user to exit that mode, for example, by pressing an ESC key and not allowing the behavior to be cancelled by the author.

Before allowing a user to select a color, browsers should ensure that the user had a chance to see the UI. This could be accomplished by enforcing a minimum time interval between opening the eyedropper and allowing color selection.

The transition into eyedropper mode should require consumable user activation, for example, clicking on a button from the web page, to help avoid unintentionally revealing pixel data.

Examples

Platform support

Selecting a color