Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

init/style Checkbox & CheckboxGroup #29

Merged
merged 23 commits into from
Aug 3, 2018
Merged

init/style Checkbox & CheckboxGroup #29

merged 23 commits into from
Aug 3, 2018

Conversation

chamkank
Copy link
Contributor

@chamkank chamkank commented Aug 1, 2018

👷 Changes

This PR adds the Checkbox and CheckboxGroup components.

Usage:

New checkbox demo

You can use Checkbox on its own but it's cleaner when wrapped with CheckboxGroup because you can have a shared name attribute (as well as shared defaultChecked, disabled, and onChange attributes). You can override a shared prop by passing a specific value for that prop to the child component.

import React from 'react';
import { Checkbox, CheckboxGroup } from '../input/buttons/CheckboxGroup';

<CheckboxGroup name="test_name">
  <Checkbox label="Label 1" value="test_value" checked="checked"/>
  <Checkbox label="Label 2" value="test_value" disabled />
  <Checkbox label="Label 3" value="test_value" name="overriden_name"/>
</CheckboxGroup>

💭 Notes

If you're curious as to what the pure CSS implementation looked like...

Old checkbox

  • Close but not close enough to the mocks, so I used the SVG images instead.

TODO

  • I still need to add styling for the disabled state
  • Also need to add Enzyme tests

🔦 Testing Instructions

make web & go to localhost:8080/ui_demo

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we pulling svg from a website? is it reliable? why not save it as part of this repo?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xmlns is XML namespacing, which iirc is used to do the svg magic - all svg's will have it

const InputContext = React.createContext();

const Checkbox = ({ name, value, label, checked, disabled, onChange }) => (
<InputContext.Consumer>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty cool, never seen this pattern before.

Would you still be able to render a Checkbox without CheckboxGroup?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IKR, it's the new context API and I like it a lot. 😃

I intended for Checkbox to be used on its own but currently it's failing without a parent CheckboxGroup. I'll fix this tomorrow, thanks!

<input
type="checkbox"
name={name || context.name}
value={value}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need value? Couldn't onChange just supply the value in the callback?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if I follow. Normally in regular forms you can have an input without an onChange function (the value is passed on form submit) and so I wanted to support that use case. I haven't played around with forms in React before, is there a reason to have the onChange without the value?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this goes for any checkbox form - checkbox is just a toggle, onChange just needs to notify if value is true or false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OH SHOOT, I've mixed up my logic, the shared name prop is only useful to radio buttons (where there is only a single answer), hence why value is there so you can distinguish between radio button options.

But this is a checkbox... 💀 , I'll fix all of this tomorrow.

Copy link
Contributor Author

@chamkank chamkank Aug 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually nevermind, the normal way of handling a group of checkboxes is to group them with the same name but have unique (string) values. Then when you submit the form, all the checked values are passed under the same name and you parse them.

<input type="checkbox" name="diet" value="vegetarian"> Vegetarian
<input type="checkbox" name="diet" value="gluten-free" checked> Gluten Free
<input type="checkbox" name="diet" value="vegan" checked> Vegan
  • On form submit this becomes diet=gluten-free&diet=vegan

We can also have unique names for each checkbox and no value (and then parse each one individually by name) but this doesn't feel right if you have a group of checkboxes because you have to prefix them to understand how they're grouped on the front-end (if you don't do this they can conflict with other names in the form which is bad practice).

<input type="checkbox" name="vegetarian"> Vegetarian
<input type="checkbox" name="gluten-free" checked> Gluten Free
<input type="checkbox" name="vegan" checked> Vegan
  • On form submit this becomes gluten-free=on&vegan=on

I'm going to stick with the first approach, any objections?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair actually, I think you're right

name: PropTypes.string,

// input value for checkbox
value: PropTypes.string.isRequired,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this be a boolean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which part are you referring to?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkbox value is either true or false, right? unless value is the label, but it looks like that's covered by name || context.name

@chamkank
Copy link
Contributor Author

chamkank commented Aug 3, 2018

Bad news lol, enzyme-adapter-react-16 doesn't support the new context API yet. Stumbled upon it while writing tests (see this error). Good news is that it's being worked on (see this issue). So no tests for this (and the radio button) until that's fixed.

Copy link
Contributor

@bobheadxi bobheadxi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

Copy link
Contributor

@bobheadxi bobheadxi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -17,6 +17,7 @@
"react/jsx-filename-extension": 0,
"react/require-default-props": 0,
"react/forbid-prop-types": 0,
"react/destructuring-assignment": 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Destructuring is awesome - why not enforce it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed CheckboxGroup to use destructuring (const { children, ...rest } = props;) but that broke another rule which was no-unused-vars (since ...rest wasn't used).

But now I realize that ...rest is optional 😛 , I'll make this change.

Copy link
Contributor

@bobheadxi bobheadxi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be good to go

"customValidators": "customValidator"
}
],
"jsx-a11y/label-has-for": [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be fine, but do you mind quickly explain what these were added for?

Copy link
Contributor Author

@chamkank chamkank Aug 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the prop-types config (it allowed me to not have to write propTypes for CheckboxGroup).

The jsx-a11y/label-has-for config was for dealing with the error related to not having a for attribute for the label. There are two ways I know of to associate labels with checkboxes (which makes the labels clickable):

<input id="some_id">
<label for="some_id">Some label<label>
<label>
  <input /> Some label
</label>

And I chose the second option. With the first one we have to either require that a unique id is passed in to each Checkbox (or we generate one for each Checkbox if it's not provided) which seemed unnecessary. The config I added allows us to use either approach - without the config it forces us to use both, which would look like this:

<label for="some_id">
  <input id="some_id" /> Some label
</label>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(it allowed me to not have to write propTypes for CheckboxGroup).

Why would you not want this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure laziness 🐢

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh wait you removed it, nevermind :D

@chamkank chamkank merged commit abb7a7b into master Aug 3, 2018
@bobheadxi bobheadxi deleted the style-checkbox branch August 3, 2018 06:18
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants