Styling drop down menus with colour

Hi all,

I just love Input.select. What an amazingly simple API.

I am wondering if there is anyway to style the selections in the dropdown menu? Specifically I am interested in adding colour to the text. So take for example this dropdown menu:

viewof menu = Inputs.select(["one", "two"], {value: "one", label: "Drop down"})

Is there any way to add these colours to the text in the dropdown?

["#20bcd2", "#d3bea6"]

Probably not.

The Input APIs seem to be simple JavaScript wrappers over the basic HTML form elements, and thatā€™s not something you can do with raw HTML at this point.

Hereā€™s a good starting point (with links): <select>: The HTML Select element - HTML: HyperText Markup Language | MDN

Does this help? Is Observable Inputs style-able? / Saneef H. Ansari | Observable

I fairly new with observable but I was hesitant to add the view dependency with that. I was hoping I could accomplish it without that.

1 Like

Looks like it should be possible. I only went so far as re-constructing Saneefā€™s example, which is not a drop-down selector, but it overall appears to work by just passing in CSS:

A few pointers:

  1. You can style a native selectā€™s options, but only when multiple=true (at least on macOS, other systems might be more lenient).
  2. A viewof element is just a DOM element with a value property. You can tweak it to your heartā€™s delight before returning it, e.g.:
    viewof menu = {
     const form = Inputs.select(["one", "two"], {value: "one", label: "Drop down", multiple: true});
     form.input.children[0].style.background = "#20bcd2";
     form.input.children[1].style.background = "#d3bea6";
     return form;
    }
    
  3. For most cases you can use Inputs.form() instead of Tomā€™s view helper.
  4. Other widgets like Inputs.radio() allow you to pass a format callback with which you can wrap your options, e.g.
    viewof menu = Inputs.radio(["one", "two"], {
      value: "one",
      label: "Drop down", multiple: true,
      format: (d, i) => htl.html`<span style=${{
        background: ["#20bcd2", "#d3bea6"][i],
        padding: "0 4px"
      }}>${d}`
    })
    
    

Iā€™m fairly certain that you can even tweak a radios widget to look like a dropdown via selectors like :checked and order. :slight_smile:

1 Like

Hacked-together demo:

2 Likes

This is SO amazing. For my purposes I really donā€™t want users to be able to select multiple but even just this thread is an absolute treasure. Thank you!

1 Like

I should probably have added that I would not recommend emulating a dropdown this way. Overlays donā€™t work well in Observable as their visible region is limited to the sandbox iframe and theyā€™ll be covered by any open or pinned editors. This particular implementation is also an accessibility nightmare. :sweat_smile:

Still, you can do quite a lot with radios. See these options for example:


Inputs.table() also lets you use radios if you set its multiple option to false:

viewof penguin = Inputs.table(penguins, {multiple: false})
1 Like