qwik-ui icon indicating copy to clipboard operation
qwik-ui copied to clipboard

RFC: Checkbox Component and Its API

Open TheMcnafaha opened this issue 9 months ago • 3 comments

Table of Contents

  • Goal
  • Background information
  • Lack of alternative solutions
  • Code overview (most important; you can scroll down to get there, links don't work on GH issues apparently)

Goal

The goal of this RFC is to obtain the best user experience for our checkbox component. Particularly, I want feedback on how to handle the API of both the simple standalone checkbox and a list of checkboxes that are all controlled by one parent checkbox.

Background information

The W3C splits checkboxes into two types: (1) two-state and (2) mixed-state. Below are two pictures, one for each W3C example:

image image

The first image shows a bunch of two-state checkboxes; you can only leave the checkboxes in the first image as "checked" or "empty". The second image shows a leading mixed-state checkbox. While the difference may not seem to be much, the mixed-state checkbox has to handle multiple unique features that can be grouped into three kinds: (A) parent-to-child behaviors, (B) child-to-parent behaviors, and (C) mixed-state behavior. Each kind of behavior is described more below:

A) parent-to-child:

  1. Marking the mixed-state as "checked" makes all of its children checkboxes as "checked" too.
  2. Marking the mixed-state as "empty makes all of its children checkboxes as "empty" too.

B) child-to-parent:

  1. If all the children checkboxes are "checked", the mixed-state checkbox is automatically left as "checked" too.
  2. If all the children checkboxes are "empty", the mixed-state checkbox is automatically left as "empty" too.

C) mixed-state:

  1. the mixed-state checkbox enters its mixed state when some, but not all, of its children checkboxes are checked. Below is an image showing what this looks like: image

Lack of alternative solutions

Nearly every current UI library has a checkbox component. Of those that have them, some implement the mixed-state functionality. Of those that have the mixed functionality, none that I've seen provide a primitive, guide, or general example on how to use their mixed-state checkbox the way the W3C outlines.

I have managed to make this work. I have attached appropriate images below showing all 3 possible states and the source code.

image image image image

Code overview

Checklist

The "Checklist* component (starts on line 5 of image above) needs to be used anytime two or more checkboxes are grouped due to ARIA. As it is, this component requires the user to pass an ID that matches text that labels the grouped checkboxes.

Mixed State Checkbox

The first checkbox (starts on line 6 of image above). This checkbox has the property of "checklist" as "true", meaning that it behaves as a mixed-state checkbox instead of the default "two-state" checkbox. This is done so that consumers don't need to use more than one component to get both two-state and mixed-state behavior. Under the hood, it looks like this: image

So, it would be easy to makes this API work instead: image

This alternative API makes the difference between the two types of checkbox more explicit at the expense of having two components. I'm 50/50 on whether it would be a good idea to make the distinction between the two components more explicit or not.

Mixed State Indicator

image Because a mixed-state checkbox must have a total of three visual state (blank, mixed,checked), the indicator supports two graphics. I currently achieve this by using two named slots: "mixed" and "true". These allow for the correct graphic/element to be shown. I think it would be a good idea to use slots here (and other places in the library too) because they allow the most amount of user-customization while notably simplifying the code structure and HTML output. The only downside is that users would need to familiarized with another Qwik-ism, but I think this is a very easy part to understand and is a valuable piece of information. Nonetheless, if I'm the only one that likes this idea, I don't have a problem adding two more components to replace the two current named slots.

I am currently calling it "ChecklistIndicator" because its meant to show the state of all the other checkboxes inside the Checklist component, but it could also just be called "MixedStateIndicator". I slightly favor the current name.

Two State Checkox

image The classic checkbox. The only notable part is the "CheckboxIndicator", which is just a way to hide or show any passed children to it based on the state of the checkbox.

Checkbox Label

Currently, any text that's passed on the checkbox becomes its label: image I need to do more testing to ensure this is the case, but assuming it was, should I still add a label component to make the label part more explicit or leave it as it is?

Naming

All names are up for improvements/suggestions.

TheMcnafaha avatar Apr 30 '24 02:04 TheMcnafaha