3

Using a React Fluent UI Modal Control, could someone please show me how to:

  1. Ensure the header and footer are not part of the scrollable content (i.e. they are 'sticky', while the main content sitting between them is scrollable if the window size is insufficient).
  2. Minimise the change in modal size as content changes - that is the window sizes to the viewport as initially, but as the content changes dynamically, the modal maintains it original size.

Below is an edited example from the relevant Microsoft documentation. I have also put it in this codepen which works (unlike the snippet). Clicking the button in the footer of the modal control alters the amount of content.

const { useBoolean } = window.FluentUIReactHooks;
const { getTheme, mergeStyleSets, FontWeights, ContextualMenu, Toggle, Modal, IDragOptions, IIconProps, Stack, IStackProps, DefaultButton, IconButton, IButtonStyles, ThemeProvider, initializeIcons, Separator, PrimaryButton } = window.FluentUIReact;

// Initialize icons in case this example uses them
initializeIcons();

const ModalBasicExample: React.FunctionComponent = () => {
  const [isModalOpen, { setTrue: showModal, setFalse: hideModal }] = useBoolean(false);
  const [pageNo, setPageNo] = React.useState(0);
  const changePage = React.useCallback(() => setPageNo(oldVal => ~oldVal),[setPageNo])
  
  const titleId = "titleId";

  return (
    <div>
      <DefaultButton onClick={showModal} text="Open Modal" />
      <Modal
        titleAriaId={titleId}
        isOpen={isModalOpen}
        onDismiss={hideModal}
        isBlocking={false}
        containerClassName={contentStyles.container}
        topOffsetFixed={true}
      >
        <div className={contentStyles.header}>
          <span id={titleId}>Lorem Ipsum</span>
          <IconButton
            styles={iconButtonStyles}
            iconProps={cancelIcon}
            ariaLabel="Close popup modal"
            onClick={hideModal}
          />
        </div>
        <div className={contentStyles.body}>
          {pageNo===0 ? <div dangerouslySetInnerHTML={{
            __html:lorem}}></div> : <p>page {pageNo}</p>}
        </div>
        <footer className={contentStyles.footer}>
          <Separator/>
          <PrimaryButton text="switch" onClick={changePage}/>
        </footer>
      </Modal>
    </div>
  );
};

const cancelIcon: IIconProps = { iconName: 'Cancel' };

const theme = getTheme();
const contentStyles = mergeStyleSets({
  container: {
    display: 'flex',
    flexFlow: 'column nowrap',
    alignItems: 'stretch',
  },
  header: [
    // eslint-disable-next-line deprecation/deprecation
    theme.fonts.xLargePlus,
    {
      flex: '1 1 auto',
      borderTop: `4px solid ${theme.palette.themePrimary}`,
      color: theme.palette.neutralPrimary,
      display: 'flex',
      alignItems: 'center',
      fontWeight: FontWeights.semibold,
      padding: '12px 12px 14px 24px',
    },
  ],
  body: {
    flex: '4 4 auto',
    padding: '0 24px 24px 24px',
    overflowY: 'hidden',
    selectors: {
      p: { margin: '14px 0' },
      'p:first-child': { marginTop: 0 },
      'p:last-child': { marginBottom: 0 },
    },
  },
  footer: {
    
  }
});

const iconButtonStyles: Partial<IButtonStyles> = {
  root: {
    color: theme.palette.neutralPrimary,
    marginLeft: 'auto',
    marginTop: '4px',
    marginRight: '2px',
  },
  rootHovered: {
    color: theme.palette.neutralDark,
  },
};

const lorem = "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc suscipit, est eget porta tempor, ante justo finibus odio, sit amet rhoncus neque velit nec leo. Morbi vitae ex a urna auctor sagittis dictum at ante. Etiam vel commodo turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dapibus malesuada luctus. Vivamus nec convallis dolor, nec condimentum ligula. Aenean blandit mi et justo rutrum, sed feugiat erat gravida. Donec sit amet eleifend mauris. Duis eget leo vel elit viverra ullamcorper. Quisque eu purus nec diam convallis suscipit.</p>".repeat(7);

const ModalBasicExampleWrapper = () => <ThemeProvider><ModalBasicExample /></ThemeProvider>;
ReactDOM.render(<ModalBasicExampleWrapper />, document.getElementById('content'))
<script src="https://unpkg.com/@fluentui/react@8/dist/fluentui-react.js"></script>
<script src="https://unpkg.com/@fluentui/react-hooks@8/dist/react-hooks.js"></script>
<div id="content"></div>
Brent
  • 4,611
  • 4
  • 38
  • 55

0 Answers0