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

Code before:
    center: 'center',
    between: 'space-between',
    around: 'space-around',
  },
  // Fixes the vertical scrollbar for menu items with icons.
  subComponentStyles: Partial<Fluent.IContextualMenuSubComponentStyles> = {
    menuItem: {
      icon: { lineHeight: 'initial' },
      subMenuIcon: { lineHeight: 'initial', height: 'auto' },
    }
  }

const
  XButton = ({ model: { name, visible = true, link, label, disabled, icon, caption, value, primary, width, path, commands } }: { model: Button }) => {
    const
      handleOnClick = (name: Id, value?: S, path?: S) => (ev: any) => {
        ev.stopPropagation()
        if (path) window.open(path, "_blank")
        else if (name.startsWith('#')) window.location.hash = name.substring(1)
        else {
          wave.args[name] = value === undefined || value
          wave.push()
        }
      },
      onClick = handleOnClick(name, value, path),
      getItemProps: (commands: Command[]) => Fluent.IContextualMenuItem[] = commands =>
        commands.map(({ name, label, caption, icon, value, data, items }) => ({
          key: name,
          text: label,
          title: caption,
          iconProps: { iconName: icon },
          data: value ?? data, disabled,
          onClick: handleOnClick(name, value),
          subMenuProps: items
            ? { items: getItemProps(items), styles: { subComponentStyles } }
            : undefined
        })),
      isIconOnly = !label && icon,
      // HACK: Our visibility logic in XComponents doesn't count with nested components, e.g. Butttons > Button.
      styles: Fluent.IButtonStyles = {
        root: {
          display: visible ? undefined : 'none',
          width: formItemWidth(width),
          minWidth: width ? 'initial' : undefined,
        },
        icon: {
          fontSize: 20,
          display: 'flex',
          alignItems: 'center'
        },
        splitButtonMenuButton: isIconOnly

Review comment (suggestion):
Wondering whether we cannot reuse the existing [toCommands](https://github.com/h2oai/wave/blob/ced07d4a630d898da5f544e283e4d7890f0b3abe/ui/src/toolbar.tsx#L87) function that solves this already. It should already have styling (instead of your own `subComponentStyles`) and onClick figured out.

Code after:
    end: 'end',
    center: 'center',
    between: 'space-between',
    around: 'space-around',
  }

const
  XButton = ({ model: { name, visible = true, link, label, disabled, icon, caption, value, primary, width, path, commands } }: { model: Button }) => {
    const
      onClick = (ev: any) => {
        ev.stopPropagation()
        if (path) window.open(path, "_blank")
        else if (name.startsWith('#')) window.location.hash = name.substring(1)
        else {
          wave.args[name] = value === undefined || value
          wave.push()
        }
      },
      isIconOnly = !label && icon,
      // HACK: Our visibility logic in XComponents doesn't count with nested components, e.g. Butttons > Button.
      styles: Fluent.IButtonStyles = {
        root: {
          display: visible ? undefined : 'none',
          width: formItemWidth(width),
          minWidth: width ? 'initial' : undefined,
        },
        icon: {
          fontSize: 20,
          display: 'flex',
          alignItems: 'center'
        },
        splitButtonMenuButton: isIconOnly
          ? { backgroundColor: cssVar('$card'), border: 'none' }
          : undefined
      }


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

    if (link) {
      return <Fluent.Link data-test={name} disabled={disabled} onClick={onClick} styles={styles}>{label}</Fluent.Link>
    }
    const btnProps: Fluent.IButtonProps = {
      text: label,
      disabled,
      onClick,
      styles,
      iconProps: { iconName: icon },