siren-js / api-browser

Siren API browser that uses Siren.js
https://siren-js.github.io/api-browser/
MIT License
2 stars 0 forks source link

Support radio fields #20

Closed dillonredding closed 1 year ago

dillonredding commented 1 year ago

Would like to support radio fields.

I propose an options extension. It would be an array of objects, each of which contain a value and optional title properties. The value property is the value that the ancestor field's value is set to when that option is picked. The title is a string to customize the label, which defaults to the option's stringified value.

{
  "name": "hogwartsHouse",
  "type": "radio",
  "options": [
    { "title": "Gryffindor", "value": "g" },
    { "title": "Hufflepuff", "value": "h" },
    { "title": "Ravenclaw", "value": "r" },
    { "title": "Slytherin", "value": "s" }
  ]
}

I think this is simpler and clearer than either extension here or here.

As for how this field is displayed, I propose using a <select> drop-drown element instead of actual radio buttons, despite the type name. Radio buttons are clunky and provide poor UX since you can't deselect a radio button. A drop-down on the other hand provides a much better UX since we can easily include a default "Select one..." (or some other label) option whose value defaults to the field's value, which could be null or undefined (absent). That way, the field can be deselected by setting the field's value back to what it was when picking the default "Select one.." option. Something like this.

miller79 commented 1 year ago

I feel supporting radio buttons should be required still. They typically imply that one of the options must be selected and there are no defaults. Microsoft has a guideline here that has some opinions when to use radio buttons vs drop-down lists that I think gives good reason to support it.

Given that, I like the options extension to have a title and a value as that will work with all selection option fields that ultimately will be sending a single value back to the server. The type becomes more of an opinionated hint. So this ends with giving you the following and allows you to follow Siren closely.

type - Optional and is a hint on the type to be rendered by a UI. Each type should be opinionated based off the value and options. If not set, defaults to text

value - Optional and default value sent when not set.

options - Optional and includes all value options with optional title defining a readable description for the value.

In checkboxes, this is expected to have one value that will return when it is checked. If the value on the field is set, then it will default to being sent checked.

In drop-down boxes, this will represent all the options to select where the value is sent to the server and the title is what is shown on the screen. If value is set, that is the default selected option if the field is not sent. If not set and the field is not sent, it should expect a failure response from the server.

In radio buttons, this will represent all the options of the radio. The title should represent the label on the radio button. If value is set, that is the default selected option if the field is not sent. If not set and the field is not sent, it should expect a failure response from the server.

In a text field, this will represent type ahead lists. If value is set, that is the default selected option if the field is not sent. If not set and the field is not sent, it should send blank.

dillonredding commented 1 year ago

From those guidelines...

Is the number of options between two and seven? Since the screen space used is proportional to the number of options, keep the number of options in a group between two and seven.

The browser cannot guarantee this. We could check options.length and choose whether to display radio buttons or a drop-down, but...

Would a drop-down list be a better choice? [...] Consider a drop-down list if there are other drop-down lists on the page.

Even Microsoft thinks mixing and matching is a bad idea.

That said, I don't want to overthink this. The browser can support Siren radio fields without displaying them as radio buttons. I think drop-down is the way to go, at least for now, since it's a better UX (e.g., try deselecting these). We can always iterate on it.

So, essentially, this (no default):

{
  "name": "hogwartsHouse",
  "type": "radio",
  "options": [
    { "title": "Gryffindor", "value": "g" },
    { "title": "Hufflepuff", "value": "h" },
    { "title": "Ravenclaw", "value": "r" },
    { "title": "Slytherin", "value": "s" }
  ]
}

Translates to this (with a "deselect" option):

<select>
  <option>Select one...</option>
  <option value="g">Gryffindor</option>
  <option value="h">Hufflepuff</option>
  <option value="r">Ravenclaw</option>
  <option value="s">Slytherin</option>
</select>

And this (with a default from the options list):

{
  "name": "hogwartsHouse",
  "type": "radio",
  "value": "r",
  "options": [
    { "title": "Gryffindor", "value": "g" },
    { "title": "Hufflepuff", "value": "h" },
    { "title": "Ravenclaw", "value": "r" },
    { "title": "Slytherin", "value": "s" }
  ]
}

Translates to this (simply preselect a value; no default):

<select>
  <option value="g">Gryffindor</option>
  <option value="h">Hufflepuff</option>
  <option value="r" selected>Ravenclaw</option>
  <option value="s">Slytherin</option>
</select>

And this (with a default not in the options list):

{
  "name": "hogwartsHouse",
  "type": "radio",
  "value": "d",
  "options": [
    { "title": "Gryffindor", "value": "g" },
    { "title": "Hufflepuff", "value": "h" },
    { "title": "Ravenclaw", "value": "r" },
    { "title": "Slytherin", "value": "s" }
  ]
}

Translates to this (default option with default value):

<select>
  <option value="d">Select one...</option>
  <option value="g">Gryffindor</option>
  <option value="h">Hufflepuff</option>
  <option value="r">Ravenclaw</option>
  <option value="s">Slytherin</option>
</select>
dillonredding commented 1 year ago

@miller79 First iteration is up. LMK what you think.

miller79 commented 1 year ago

Works good for me thanks!