Skip to content

Conversation

@jonkafton
Copy link
Contributor

@jonkafton jonkafton commented Jun 26, 2024

What are the relevant tickets?

Closes https://github.com/mitodl/hq/issues/4661

Description (What does it do?)

Updates the styles and hover states for the ChoiceBox and its field grid.

Also:

  • Provides a Checkbox and Radio in ol-components
  • Exports styles for reuse (applies to the SearchDisplay course-search-utils overrides).
  • Adds Storybook stories for ChoiceBox.
  • Removes the hidden input control in ChoiceBox (accessibility concern) to style directly.
  • Upgrades Storybook.

Screenshots (if appropriate):

image
image
image
image

How can this be tested?

  • While authenticated, navigate to /onboarding and step through the onboarding screens.
  • See also the ChoiceBox, ChoiceBoxField and Checkbox stories in Storybook
    • /?path=/story/ol-components-choicebox--checkbox
    • /?path=/story/ol-components-choiceboxfield--checkbox
    • /?path=/story/ol-components-checkbox--simple

@ChristopherChudzicki ChristopherChudzicki removed their assignment Jun 26, 2024
@jonkafton jonkafton added Needs Review An open Pull Request that is ready for review Work in Progress and removed Work in Progress Needs Review An open Pull Request that is ready for review labels Jun 26, 2024
@jonkafton jonkafton changed the title Updates to ChoiceBox and a Checkbox component Updates to ChoiceBox; Checkbox, Radio components Jun 26, 2024
@jonkafton jonkafton added Needs Review An open Pull Request that is ready for review and removed Work in Progress labels Jun 26, 2024
@ChristopherChudzicki ChristopherChudzicki self-assigned this Jun 27, 2024
Comment on lines 46 to 48
const fieldGridItemProps = {
...gridItemProps,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

out of curiosity, any reason to spread 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.

Nope 🤷‍♂️

)
}

Radio.styles = containerStyles
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this for re-use? I had no idea typescript would let you do this without declaring the property on Radio beforehand. Interesting.

Suggestion: wrap it in css() from import { css } from "@emotion/react". That will allow it to work with either the object or template literal syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice. It won't work outside of Emotion though if we need it as plain css, which I guess we don't (ie. can't be interpolated - its toString() method returns a warning message).

Comment on lines 9 to 11
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setChecked(event.target.checked)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

**Suggestion: ** call action("changed")(event)

from import { action } from "@storybook/addon-actions"

Comment on lines +10 to +12
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setChecked(event.target.checked)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

**Suggestion: ** call action("changed")(event)

from import { action } from "@storybook/addon-actions"

Comment on lines +27 to +28
const target = event.target as HTMLInputElement
if (target.checked) {
Copy link
Contributor

Choose a reason for hiding this comment

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

**Suggestion: ** call action("changed")(event)

from import { action } from "@storybook/addon-actions"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I achieved the same with this on the meta:

argTypes: {
    onChange: {
        action: "change"
    }
}

and calling props.onChange?.(event) in our StateWrapper.

const [checked, setChecked] = useState(!!props.checked)

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setChecked(event.target.checked)
Copy link
Contributor

Choose a reason for hiding this comment

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

**Suggestion: ** call action("changed")(event)

from import { action } from "@storybook/addon-actions"

return (
<ChoiceBoxField
type="checkbox"
isChecked={(choice) => values?.indexOf(choice.value) !== -1}
Copy link
Contributor

Choose a reason for hiding this comment

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

values?.includes(...) 🤷

)
}

export { ChoiceBoxField, CheckboxChoiceBoxField, RadioChoiceBoxField }
Copy link
Contributor

Choose a reason for hiding this comment

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

My inclination would be to not export ChoiceBoxField, at least for now.

May also want to add a docstring to to ChoiceBoxField along lines of

/**
 * Prefer using `CheckboxChoiceBoxField` or `RadioChoiceBoxField` instead of
 * this component, where possible.
 */

The only case I can think of where you'd use ChoiceBoxField directly would be if you needed a checkbox with the "partially checked" state?

Copy link
Contributor Author

@jonkafton jonkafton Jun 27, 2024

Choose a reason for hiding this comment

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

True. We need the wrapping components for the different isChecked workings.

The naming Field isn't great here. Technically they're fieldsets. Thoughts on RadioChoiceBoxFieldset or even RadioChoiceBoxGrid?

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO... "Field" is fine. "Field" is not a technical HTML term as far as I know. (In contrast to fieldset—please educate me if I am mistaken!). *I.e., I don't equate "field" with "single input element".

RadioGroup is a good name for the radio version (after `role="radiogroup"—which we could add, but isn't really necessary afaik since we are using native radio elements). But there's not checkboxgroup role.

Leaving *Field seems fine to me.

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 see it as an individual form field (ie. an input) as opposed to a fieldset containing multiple - the ChoiceBoxField container element is an html fieldset.

Comment on lines 55 to 57
<FormLabel component="legend" sx={{ width: "100%" }}>
{label}
</FormLabel>
Copy link
Contributor

Choose a reason for hiding this comment

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

A few overall comments here:

  1. It would be nice to be able to support required and an error message.

  2. I'm not sure what FormControl gives us. My understanding is that MUI uses this to wrap its inputs to manage some internal state. See https://mui.com/base-ui/react-form-control/. I chose not to use it for our TextField, and instead we have FormFieldWrapper in FormHelpers.

    • That said, FormFieldWrapper isn't directly directly usable here. It's expecting a single input, like select or text.
    • That said, the error message / description / required components in FormHelpers might be helpful.
  3. I don't think we have very explicit component designs for ChoiceBoxField, but it seems to me it should match https://www.figma.com/design/Eux3guSenAFVvNHGi1Y9Wm/MIT-Design-System?node-id=4345-87576&m=dev :

    Screenshot 2024-06-27 at 11 58 24 AM

    I.e., the legend currently doesn't have the style we want.

My inclination for actionable steps right now:

  • Make title match profile page style (i.e., subtitle2, which is what the textfield and selectfield labels use, too)
  • add spot for overall description + error message, using styles from FormHelpers. You could alter FormFieldWrapper and use it, if you see fit. But the spacing between legend and input is also a little different, I think. 8px not 4px.

interface ChoiceBoxFieldProps extends BaseChoiceBoxFieldProps {
type: ChoiceBoxProps["type"]
name?: string
isChecked: (choice: ChoiceBoxChoice) => boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment: I can imagine isDisabled would also be useful, but I don't think we need to add it now.

@ChristopherChudzicki
Copy link
Contributor

Adding this as a requested change... I do think we should do something about this alignment issue:

Screenshot 2024-06-27 at 12 18 19 PM

I manually edited a title, there, but note alignment on Figma dashboard page.

Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki left a comment

Choose a reason for hiding this comment

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

Requested change is the alignment issue.

@jonkafton
Copy link
Contributor Author

These changes also pushed:

  • Style the title (fieldset legend) to match designs
  • Remove the label+input center alignment and restyle so the input control remains anchored top for multiline labels

Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki left a comment

Choose a reason for hiding this comment

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

👍

@ChristopherChudzicki ChristopherChudzicki added Waiting on author and removed Needs Review An open Pull Request that is ready for review labels Jun 27, 2024
@jonkafton jonkafton merged commit 38eb61c into main Jun 28, 2024
@jonkafton jonkafton deleted the jk/4661-choicebox branch June 28, 2024 12:26
This was referenced Jul 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants