Select in Form is not displayed completely when using Custom UI

I created a Jira gadget based on the Custom UI and added a Form with a Select and a Save button at the bottom. The Select has 4 options, but the dropdown is not displayed completely.

See also screenshot. I added the gadget twice to my dashboard and in the right panel I clicked on the function dropdown to open it. Only the top part of the first option is displayed.

Basically, the code I have is like

import React, { Fragment, useEffect, useState } from 'react';
import Form, { Field , ErrorMessage} from '@atlaskit/form';
import TextField from '@atlaskit/textfield';
import Select from '@atlaskit/select';
import Button, { ButtonGroup } from '@atlaskit/button';
import { view } from '@forge/bridge';

const FUNCTIONS = [{"label" : "Sum", value:"sum"},
                     {"label" : "Average", value:"avg"},
                     {"label" : "Minimum", value:"min"},
                     {"label" : "Maximum", value:"max"}];

function Edit({context}) {
    const [configuration, setConfiguration] = useState();

    const onSubmit = (formData) => {
         view.submit(formData);
    }

    useEffect(() => {
        setConfiguration(context.extension.gadgetConfiguration);
    }, []);

    if (!configuration ) {
        return 'Loading...';
    }

    return (
        <Form onSubmit={onSubmit}>
            {({ formProps, submitting }) => (
                <form {...formProps}>
                    <Field name="fn" label="Function">
                        {({ fieldProps: { ...rest }, error }) =>
                            <Fragment>
                                 <Select
                                    defaultValue={
                                       configuration.fn ?
                                            { label: configuration.fn.label,
                                              value: configuration.fn.value }
                                       : ""}
                                    options={FUNCTIONS}
                                     {...rest}/>
                            </Fragment>
                         }
                    </Field>
                    <ButtonGroup>
                        <Button type="submit" isDisabled={submitting}>Save</Button>
                        <Button appearance="subtle" onClick={view.close}>Cancel</Button>
                    </ButtonGroup>
                </form>
            )}
        </Form>
    );
}

export default Edit;

The dependencies are defined in the package.json like this

"dependencies": {
    "@atlaskit/button": "^17.14.2",
    "@atlaskit/css-reset": "^6.9.0",
    "@atlaskit/form": "^10.0.0",
    "@atlaskit/select": "^17.9.0",
    "@atlaskit/textfield": "^6.3.1",
    "@atlaskit/tooltip": "^18.4.0",
    "@forge/bridge": "^3.4.0",
    "react": "^16.14.0",
    "react-dom": "^16.14.0"
  }

How can I force to display the dropdown completely? Thanks in advance.

I have a more or less same issue with a tooltip. The tooltip can be long, but only the top part is rendered.

The code to display the text with a tooltip is like

import Tooltip from '@atlaskit/tooltip';
import EditorPanelIcon from '@atlaskit/icon/glyph/editor/panel'

function TextWithTooltip({text, tooltipText, fontSize}) {

    return (
        <div style={{ textAlign: 'center', fontSize: fontSize}} >
            <Tooltip content={tooltipText}>
                {(tooltipProps) =>
                    <div {...tooltipProps}>
                        {text}
                        <span style={{verticalAlign: 'super'}}>
                            <EditorPanelIcon size="large" label=""/>
                        </span>
                    </div>
                }
            </Tooltip>
        </div>
    );
}

export default TextWithTooltip;

Hi @kvaaca I think this is due to the fact that Custom UI runs within an iframe so when the iframe initially loads the width and height is sized to your select component in its unopened state. Once you interact with the select component to see the list of options, however, the iframe doesn’t get resized to fit the additional height required to display the additional elements.

You can try modifying the viewport size or maybe wrap your form inside a div with a predefined height although I think this is generally less recommended.

Edit: looks like setting a viewport size isn’t possible with the jira gadget module.

You can do something dumb by using setting a height this way by using onMenuOpen/onMenuClose:

function Edit({ context }) {
  const [configuration, setConfiguration] = useState();
  const [height, setHeight] = useState();
  const onSubmit = (formData) => {
    view.submit(formData);
  };

  useEffect(() => {
    console.log("context.extension :", context.extension);
    setConfiguration(context.extension.gadgetConfiguration);
  }, []);

  if (!configuration) {
    return "Loading...";
  }

  return (
    <div style={{ height }}>
      <Form onSubmit={onSubmit}>
        {({ formProps, submitting }) => (
          <form {...formProps}>
            <Field name="fn" label="Function">
              {({ fieldProps: { ...rest }, error }) => (
                <Fragment>
                  <Select
                    defaultValue={
                      configuration.fn
                        ? {
                            label: configuration.fn.label,
                            value: configuration.fn.value,
                          }
                        : ""
                    }
                    onMenuOpen={() => setHeight(500)}
                    onMenuClose={() => setHeight(undefined)}
                    options={FUNCTIONS}
                    {...rest}
                  />
                </Fragment>
              )}
            </Field>
            <ButtonGroup>
              <Button type="submit" isDisabled={submitting}>
                Save
              </Button>
              <Button appearance="subtle" onClick={view.close}>
                Cancel
              </Button>
            </ButtonGroup>
          </form>
        )}
      </Form>
    </div>
  );
}

You can further constrain the size of the select list by using the maxMenuHeight prop and setting it to less than the height of your div to make sure it doesn’t overflow.

Update: here’s a smarter way of doing it:

function Edit({ context }) {
  const [configuration, setConfiguration] = useState();
  const [height, setHeight] = useState();
  const ref = useRef();

  const onSubmit = (formData) => {
    view.submit(formData);
  };

  useEffect(() => {
    setConfiguration(context.extension.gadgetConfiguration);
  }, []);

  if (!configuration) {
    return "Loading...";
  }

  const setformheight = () => {
    setTimeout(() => {
      const containerHeight = ref.current.getBoundingClientRect().height;

      const selectHeight = ref.current
        .querySelector("#react-select-gadget-listbox")
        .getBoundingClientRect().height;

      setHeight(containerHeight + selectHeight);
    }, 0);
  };

  return (
    <div style={{ height }} ref={ref}>
      <Form onSubmit={onSubmit}>
        {({ formProps, submitting }) => (
          <form {...formProps}>
            <Field name="fn" label="Function">
              {({ fieldProps: { ...rest }, error }) => (
                <Fragment>
                  <Select
                    instanceId="gadget"
                    style={{ background: "black" }}
                    defaultValue={
                      configuration.fn
                        ? {
                            label: configuration.fn.label,
                            value: configuration.fn.value,
                          }
                        : ""
                    }
                    onMenuOpen={setformheight}
                    onMenuClose={() => setHeight(undefined)}
                    options={FUNCTIONS}
                    {...rest}
                  />
                </Fragment>
              )}
            </Field>
            <ButtonGroup>
              <Button type="submit" isDisabled={submitting}>
                Save
              </Button>
              <Button appearance="subtle" onClick={view.close}>
                Cancel
              </Button>
            </ButtonGroup>
          </form>
        )}
      </Form>
    </div>
  );
}

You might want to make the div container a flexbox so that the select list isn’t covering it when it’s in an open state but I’ll leave that as an exercise for you.

1 Like

FYI [FRGE-1121] - Ecosystem Jira