Repository: h2oai/wave
File: ui/src/choice_group.tsx (TypeScript)

Code before:
  /** The name of the selected choice. */
  value?: S
  /** The choices to be presented. */
  choices?: Choice[]
  /** True if this field is required. */
  required?: B
  /** True if the form should be submitted when the selection changes. */
  trigger?: B
  /** True if choices should be rendered horizontally. Defaults to False. */
  inline?: B
  /** The width of the choice group, e.g. '100px'. */
  width?: S
  /** True if the component should be visible. Defaults to True. */
  visible?: B
  /** An optional tooltip message displayed when a user clicks the help icon to the right of the component. */
  tooltip?: S
}

const
  css = stylesheet({
    inline: {
      $nest: {
        '.ms-ChoiceFieldGroup-flexContainer': {
          display: 'flex',
          flexWrap: 'wrap',
        },
        '.ms-ChoiceField': {
          marginRight: 15,
        }
      }
    }
  })

export const
  XChoiceGroup = ({ model: m }: { model: ChoiceGroup }) => {
    const
      options = (m.choices || []).map(({ name, label, disabled }): Fluent.IChoiceGroupOption => ({ key: name, text: label || name, disabled })),
      onChange = (_e?: React.FormEvent<HTMLElement>, option?: Fluent.IChoiceGroupOption) => {
        if (option) wave.args[m.name] = option.key
        if (m.trigger) wave.push()
      }

    // eslint-disable-next-line react-hooks/exhaustive-deps
    React.useEffect(() => { wave.args[m.name] = m.value || null }, [])

    return (
      <Fluent.ChoiceGroup
        className={m.inline ? css.inline : ''}
        data-test={m.name}
        label={m.label}
        required={m.required}

Review comment (bug):
Prefer to use Fluent way of restyling (using `styles` prop on component) when possible. If Fluent team decides to change the CSS class name, we will not know, but if they change the TS API our build will fail so that we can fix it ourselves.

Code after:
  value?: S
  /** The choices to be presented. */
  choices?: Choice[]
  /** True if this field is required. */
  required?: B
  /** True if the form should be submitted when the selection changes. */
  trigger?: B
  /** True if choices should be rendered horizontally. Defaults to False. */
  inline?: B
  /** The width of the choice group, e.g. '100px'. */
  width?: S
  /** True if the component should be visible. Defaults to True. */
  visible?: B
  /** An optional tooltip message displayed when a user clicks the help icon to the right of the component. */
  tooltip?: S
}

export const
  XChoiceGroup = ({ model: m }: { model: ChoiceGroup }) => {
    const
      optionStyles = { choiceFieldWrapper: { marginRight: 15 } },
      options = (m.choices || []).map(({ name, label, disabled }): Fluent.IChoiceGroupOption => ({ key: name, text: label || name, disabled, styles: optionStyles })),
      onChange = (_e?: React.FormEvent<HTMLElement>, option?: Fluent.IChoiceGroupOption) => {
        if (option) wave.args[m.name] = option.key
        if (m.trigger) wave.push()
      }

    // eslint-disable-next-line react-hooks/exhaustive-deps
    React.useEffect(() => { wave.args[m.name] = m.value || null }, [])

    return (
      <Fluent.ChoiceGroup
        styles={{ flexContainer: { display: 'flex', flexWrap: 'wrap' } }}
        data-test={m.name}
        label={m.label}
        required={m.required}
        defaultSelectedKey={m.value}
        options={options}
        onChange={onChange}
      />
    )

  }