-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Checkbox Component and Its API #729
Comments
First off, A.M.A.Z.I.N.G RFC! Really cool! Thanks @TheMcnafaha! Now I have a couple of questions/remarks 🕺:
|
Thanks for the feedback @maiieul
Yes, the components should be moved to the dot syntax.
I'd be happy to do this. I'll try to make a report on the components that I think would be benefited the most by the end of next month.
Yes.
I hadn't considered the part you mentioned in the second sentence. I will try to make the native label work as you suggested too. |
I really enjoy the depth you've explained here @TheMcnafaha. After reading through the RFC, here's some of my thoughts: checkList propThe Perhaps we can use an inline component in the Checklist to check for the existence of A labelThe preferred way to compute an accessible name whenever possible, is visual content and the use of In the select, I check if the The fallback is the content inside of the Select. If the user wants to make the content inside the component hidden, they can use our We want to create experiences that are tailored to our applications, and this seems to be what Kobalte UI has done, by providing these components for accessible names, descriptions, error states, etc. SlotsThe slots are pretty off putting to me, for someone to know how to use it, they would need to look through a specific portion of the docs, which is likely going to add frustration, or at the very least, be harder to manage than a component included in the dot notation syntax (or the top of the docs & in code examples). Checklist & Checkbox: Two components?My biggest concern here would be intuitive customization. By that I mean, what would people expect? Another thing to mention, is that it is similar to how the disclosure and accordion components work. It seems to me that a Checklist could be another new component, built on top of the Checkbox primitive. I think both are pretty declarative of what they do, and a similar separation of what we have to the disclosure + accordion makes sense. I could also see it being one component and then the checklist being an advanced section of the docs. Amazing@TheMcnafaha this is a big let him cook moment. 👨🍳 awesome job so far, look forward to trying it out. |
Table of Contents
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:
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:
B) child-to-parent:
C) mixed-state:
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.
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](https://private-user-images.githubusercontent.com/102767512/326635249-97f647e4-c691-4843-ab45-50db80a09dc0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxNTE1MTMsIm5iZiI6MTcyNDE1MTIxMywicGF0aCI6Ii8xMDI3Njc1MTIvMzI2NjM1MjQ5LTk3ZjY0N2U0LWM2OTEtNDg0My1hYjQ1LTUwZGI4MGEwOWRjMC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODIwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyMFQxMDUzMzNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0wYTczMTNjMTZmODg5OTU0YjBiNjZkZmU5M2VhNGMzYzQ3MTc2YzM1NmFhZTJjZDU2ODMwM2Q0MTZmM2I3ZjYxJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.nMrN8STiZ27nUJDrjrpnLwPDYgP7EOdRddu4Tnx6LeQ)
So, it would be easy to makes this API work instead:
![image](https://private-user-images.githubusercontent.com/102767512/326636964-3b69a28a-f955-45a0-9521-fc0ac11a1a15.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxNTE1MTMsIm5iZiI6MTcyNDE1MTIxMywicGF0aCI6Ii8xMDI3Njc1MTIvMzI2NjM2OTY0LTNiNjlhMjhhLWY5NTUtNDVhMC05NTIxLWZjMGFjMTFhMWExNS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODIwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyMFQxMDUzMzNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT02ZDVjZDRhMzA2YTNmMjkwNzZmMTZkMDkzODY2ZmZiYjdlYzY0MWQ4YzFhZTZlZjA1OWUzNjI3NzliYzNhNWQyJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.3IlKSZuApdlgTtJXcYhDsBv24AcwFVBIaRKXl5NwZ7M)
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
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
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](https://private-user-images.githubusercontent.com/102767512/326643104-666874be-100d-4af6-bf41-a3cb60ae226a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQxNTE1MTMsIm5iZiI6MTcyNDE1MTIxMywicGF0aCI6Ii8xMDI3Njc1MTIvMzI2NjQzMTA0LTY2Njg3NGJlLTEwMGQtNGFmNi1iZjQxLWEzY2I2MGFlMjI2YS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODIwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgyMFQxMDUzMzNaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lNGI1Nzc5M2IyNzEzMzNjMjA4YzI1ODE2MjgxZDhhMTcyYzQ5ODYwZmVkZTI5YjllZmIwMjg1MzRkMGYzOGI3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.d0idyYPwGbgoCpiHPAYkI9x6RGzWH_JwadPBq6g_rBs)
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.
The text was updated successfully, but these errors were encountered: