Code Study: GitHub Desktop / ui / toolbar / dropdown.tsx

The file defines the ToolbarDropdown component.

A ToolbarDropdown is composed of the dropdown content and a ToolbarButton wrapped in a div.

<div
  className={className}
  onKeyDown={this.props.onKeyDown}
  role={this.props.role}
  aria-expanded={ariaExpanded}
>
  {this.renderDropdownContents()}
  <ToolbarButton
    ref={this.onRef}
    icon={this.props.icon}
    title={this.props.title}
    description={this.props.description}
    tooltip={this.props.tooltip}
    onClick={this.onClick}
    onMouseEnter={this.props.onMouseEnter}
    style={this.props.style}
    iconClassName={this.props.iconClassName}
    disabled={this.props.disabled}
    tabIndex={this.props.tabIndex}
    progressValue={this.props.progressValue}
    role={this.props.buttonRole}
  >
    {this.props.children}
    {this.renderDropdownArrow()}
  </ToolbarButton>
</div>

The dropdown content is rendered as

<div id="foldout-container" style={this.getFoldoutContainerStyle()}>
  <div
    className="overlay"
    tabIndex={-1}
    onClick={this.handleOverlayClick}
  />
  <div
    className="foldout"
    style={this.getFoldoutStyle()}
    onKeyDown={this.onFoldoutKeyDown}
  >
    {this.props.dropdownContentRenderer()}
  </div>
</div>

To use the ToolbarDropdown:

<ToolbarDropdown
  ref={this.onDropDownRef}
  key={item.id}
  dropdownState={dropDownState}
  onDropdownStateChanged={this.onDropdownStateChanged}
  dropdownContentRenderer={this.dropDownContentRenderer}
  showDisclosureArrow={false}
  onMouseEnter={this.onMouseEnter}
  onKeyDown={this.onKeyDown}
  tabIndex={-1}
  role="menuitem"
>
  <MenuListItem
    item={item}
    highlightAccessKey={this.props.highlightMenuAccessKey}
    renderAcceleratorText={false}
    renderSubMenuArrow={false}
  />
</ToolbarDropdown>

And the dropDownContentRenderer can specify what content to display when user clicks the dropdown button. For example, here we display the AppMenu component in the dropdown.

private dropDownContentRenderer = () => {
  const menuState = this.props.menuState
  if (!this.isMenuOpen) {
    return null
  }
  return (
    <AppMenu
      dispatcher={this.props.dispatcher}
      onClose={this.onMenuClose}
      openedWithAccessKey={this.props.openedWithAccessKey}
      state={menuState}
      enableAccessKeyNavigation={this.props.enableAccessKeyNavigation}
      autoHeight={true}
    />
  )
}
tags: GitHub Desktop - Electron - React