代码之家  ›  专栏  ›  技术社区  ›  Eric Legault

Office UI结构的布局问题

  •  0
  • Eric Legault  · 技术社区  · 6 年前

    [编辑:更新以将问题集中在覆盖问题上;还对代码笔进行了编辑] [编辑2:更新后包含穆罕默德·曼苏尔建议的方法的详细信息]

    我很难为OfficeUI结构的React UI设计布局。这是我目前拥有的布局:

    enter image description here

    目标是使顶部的命令栏和标题(文本标签和搜索框)固定在顶部,而详细信息列表和归档按钮固定在底部,并在标题区域后尽可能占用空间。

    我已经成功地使用了可滚动窗格和两个粘性组件将命令栏和按钮锚定在所需的位置。但是,detailslist会滚动显示包含命令栏和标题的最上面的粘性内容,并且该按钮稍微覆盖在detailslist网格的顶部:

    enter image description here

    我试过使用FabricGrid组件来布局所有部分,但这并没有什么区别(如果它有任何帮助的话)。最佳布局在两个粘性元素之间有项目部分;如果将项目部分添加到页眉或页脚粘性元素中,则布局很糟糕。如何确保详细信息列表不会在顶部和底部组件下滚动?

    下面是两个说明问题的代码笔:

    无网格: https://codepen.io/elegault/pen/aQayvY?editors=0010 (文件头为其元素使用网格,但所有其他元素不在网格中)

    const columns = [{
      key: 'projectNameColumn',
      name: 'Project',
      fieldName: 'name',
      minWidth: 100,
      maxWidth: 200,
      isResizable: true,
      ariaLabel: 'Operations for Project'
    }];
    const items = [{
        id: '0',
        name: 'ABC Construction'
      },
      {
        id: '1',
        name: 'Air Bee and Bee'
      },
      {
        id: '2',
        name: 'Architectural Salvage'
      },
      {
        id: '3',
        name: 'Arkham Airport'
      },
      {
        id: '4',
        name: 'Arkham Assembly Hall'
      },
      {
        id: '5',
        name: 'Arkham Library'
      },
      {
        id: '6',
        name: 'zArkham Renovation'
      },
      {
        id: '7',
        name: 'Foo'
      },
      {
        id: '8',
        name: 'Foo1'
      },
      {
        id: '9',
        name: 'Foo2'
      },
      {
        id: '10',
        name: 'Foo3'
      },
      {
        id: '11',
        name: 'Foo4'
      },
      {
        id: '12',
        name: 'Foo5'
      },
      {
        id: '13',
        name: 'Foo6'
      },
      {
        id: '14',
        name: 'Foo7'
      },
      {
        id: '15',
        name: 'Foo8'
      },
      {
        id: '16',
        name: 'Foo9'
      },
      {
        id: '17',
        name: 'Foo10'
      },
    ];
    class Content extends React.Component {
      public render() {
        const fileHeader = <
          div className = 'ms-Grid' >
          <
          div className = 'ms-Grid-row' >
          <
          div className = 'ms-Grid-col ms-sm2 ms-md2 ms-lg2' >
          <
          img width = '32'
        height = '32'
        alt = 'logo'
        title = 'logo' / >
          <
          /div> <
          div className = 'ms-Grid-col ms-sm10 ms-md10 ms-lg10' >
          <
          Fabric.Label className = 'ms-font-l ms-fontWeight-bold ms-fontColor-blue' > [TITLE] < /Fabric.Label> <
          /div> <
          /div> <
          div className = 'ms-Grid-row' >
          <
          div className = 'ms-Grid-col ms-sm2 ms-md2 ms-lg2' >
          <
          /div> <
          div className = 'ms-Grid-col ms-sm10 ms-md10 ms-lg10' >
          <
          Fabric.Label
        className = 'ms-font-m ms-fontWeight-bold ms-fontColor-neutralPrimary' > SELECTED PROJECT: < /Fabric.Label> <
          /div> <
          /div> <
          /div>;
    
        const commandBar = < div >
          <
          Fabric.CommandBar
        isSearchBoxVisible = {
          false
        }
        items = {
          [{
            key: 'openWebApp',
            name: 'Open Web App',
            icon: 'OpenInNewWindow', // Or Link
            ['data-automation-id']: 'openWebAppButton',
            title: 'Open web app',
            href: 'http://www.codepen.io',
            target: '_blank',
          }]
        }
        farItems = {
          [{
            key: 'menuOptions',
            name: 'Options',
            icon: 'Settings',
            iconOnly: 'true',
            ['data-automation-id']: 'settingsButton',
            subMenuProps: {
              items: [{
                  key: 'privacyPolicy',
                  name: 'Privacy Policy',
                  icon: 'PageLock',
                  href: 'http://www.codepen.io',
                  target: '_blank',
    
                },
                {
                  key: 'termsOfUse',
                  name: 'Terms & Conditions',
                  icon: 'TextDocument',
                  href: 'http://www.codepen.io',
                  target: '_blank'
                }
              ]
            }
          }]
        }
        /> <
        /div>;
    
        const projects = < Fabric.MarqueeSelection selection = {
          null
        }
        data - is - scrollable = {
            false
          } >
          <
          Fabric.DetailsList
        items = {
          items
        }
        columns = {
          columns
        }
        /> <
        /Fabric.MarqueeSelection>;
        const selection = < div > [project name] < /div>;
        const search = < Fabric.TextField label = 'Search projects:' / > ;
        const fileButton = <
          div >
          <
          Fabric.DefaultButton primary = {
            true
          } > File To Project < /Fabric.DefaultButton> <
          /div>;
    
        return ( <
          Fabric.Fabric >
          <
          div style = {
            {
              height: '500px',
              position: 'relative',
              maxHeight: 'inherit'
            }
          } >
          <
          Fabric.ScrollablePane scrollbarVisibility = {
            Fabric.ScrollbarVisibility.auto
          } >
          <
          Fabric.Sticky stickyPosition = {
            Fabric.StickyPositionType.Header
          } > {
            commandBar
          } {
            fileHeader
          } {
            selection
          } {
            search
          } <
          /Fabric.Sticky>     {
            projects
          } <
          Fabric.Sticky stickyPosition = {
            Fabric.StickyPositionType.Footer
          } > {
            fileButton
          } <
          /Fabric.Sticky>       <
          /Fabric.ScrollablePane> <
          /div> <
          /Fabric.Fabric>
        );
      }
    }
    
    ReactDOM.render( <
      Content / > ,
      document.getElementById('content')
    );

    全网格: https://codepen.io/elegault/pen/wQxoRR

    const columns = [
        {
            key: 'projectNameColumn',
            name: 'Project',
            fieldName: 'name',
            minWidth: 100,
            maxWidth: 200,
            isResizable: true,
            ariaLabel: 'Operations for Project'
        }
    ];
    const items = [
        {id: '0', name: 'ABC Construction'},
        {id: '1', name: 'Air Bee and Bee'},
        {id: '2', name: 'Architectural Salvage'},
        {id: '3', name: 'Arkham Airport'},
        {id: '4', name: 'Arkham Assembly Hall'},
        {id: '5', name: 'Arkham Library'},
        {id: '6', name: 'zArkham Renovation'},
        {id: '7', name: 'Foo'},
        {id: '8', name: 'Foo1'},
        {id: '9', name: 'Foo2'},
        {id: '10', name: 'Foo3'},
        {id: '11', name: 'Foo4'},
        {id: '12', name: 'Foo5'},
        {id: '13', name: 'Foo6'},
        {id: '14', name: 'Foo7'},
        {id: '15', name: 'Foo8'},
        {id: '16', name: 'Foo9'},
        {id: '17', name: 'Foo10'},
    ];
    class Content extends React.Component {
        public render() {        
    		      
    		const commandBar = <div>
                <Fabric.CommandBar
                    isSearchBoxVisible={false}
                    items={[
                        {
                            key: 'openWebApp',
                            name: 'Open Web App',
                            icon: 'OpenInNewWindow', // Or Link                        
                            title: 'Open web app',
                            href: 'http://www.codepen.io',
                            target: '_blank',
                        }
                    ]}
                    farItems={[
                        {
                            key: 'menuOptions',
                            name: 'Options',
                            icon: 'Settings',
                            iconOnly: 'true',
                            ['data-automation-id']: 'settingsButton',
                            subMenuProps: {
                                items: [
                                    {
                                        key: 'privacyPolicy',
                                        name: 'Privacy Policy',
                                        icon: 'PageLock',
                                        href: 'http://www.codepen.io',
                                        target: '_blank',
    
                                    },
                                    {
                                        key: 'termsOfUse',
                                        name: 'Terms & Conditions',
                                        icon: 'TextDocument',
                                        href: 'http://www.codepen.io',
                                        target: '_blank'
                                    }
                                ]
                            }
                        }
                    ]}
                />
            </div>;
          
            const projects = <Fabric.MarqueeSelection selection={null} data-is-scrollable={false}>
                <Fabric.DetailsList
                    items={items}
                    columns={columns}              
                />
            </Fabric.MarqueeSelection>;
            const selection = <div>[project name]</div>;
            const search = <Fabric.TextField label='Search projects:'/>;
            const fileButton = 
                  <div>
                    <Fabric.DefaultButton primary={true}>File To Project</Fabric.DefaultButton>
                  </div>;
    		
    		    const fileHeader =             
                <div className='ms-Grid'>
                    <div className='ms-Grid-row'>
                        <div className='ms-Grid-col ms-sm2 ms-md2 ms-lg2'>
                            <img width='32' height='32' alt='logo' title='logo'/>
                        </div>
                        <div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
                            <Fabric.Label className='ms-font-l ms-fontWeight-bold ms-fontColor-blue'>[TITLE]</Fabric.Label>
                        </div>
                    </div>
                    <div className='ms-Grid-row'>
                        <div className='ms-Grid-col ms-sm2 ms-md2 ms-lg2'>
                        </div>
                        <div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
                            <Fabric.Label
                                className='ms-font-m ms-fontWeight-bold ms-fontColor-neutralPrimary'>SELECTED PROJECT:</Fabric.Label>
                        </div>
                    </div>
                </div>;
    			
            return (
    			<Fabric.Fabric>                
    				<div style={{height:'500px', position:'relative', maxHeight:'inherit'}}>										
              <Fabric.ScrollablePane scrollbarVisibility={Fabric.ScrollbarVisibility.auto}>
    						<div className='ms-Grid'>
    							<Fabric.Sticky stickyPosition={Fabric.StickyPositionType.Header}>
    								<div className='ms-Grid-row'>
    									<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    										{commandBar}
    									</div>
    								</div>								
    								<div className='ms-Grid-row'>
    									<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    										{fileHeader}
    									</div>
    								</div>									
    								<div className='ms-Grid-row'>
    									<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    										{selection}
    									</div>
    								</div>							
    								<div className='ms-Grid-row'>
    									<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    										{search}            
    									</div>
    								</div>																		
    							</Fabric.Sticky>    
    							<div className='ms-Grid-row'>
    								<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    									{projects}            
    								</div>
    							</div>								                      
    							<Fabric.Sticky stickyPosition={Fabric.StickyPositionType.Footer}>						
    								<div className='ms-Grid-row'>
    									<div className='ms-Grid-col ms-sm10 ms-md10 ms-lg10'>
    										{fileButton}            
    									</div>
    								</div>								
    							</Fabric.Sticky>      
    						</div>
              </Fabric.ScrollablePane>
    				</div>
          </Fabric.Fabric>
            );			
    		
        }
    }
    
    ReactDOM.render( 
      <Content />,
      document.getElementById('content')
    );

    此外,当试图在使用嵌套自定义反应组件的代码笔之外的项目中使用flex类或父div(根据Mohamed Mansour的建议)中定义的高度时,整个detailsList无法呈现。例如,此DOM资源管理器显示了即使在多个“主”分区中设置定义的高度和使用flex也无法呈现详细信息列表:

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  0
  •   Mohamed Mansour    6 年前

    让我们澄清一些术语,这些术语来自文档:

    • ScrollablePane :使用绝对定位,父级必须具有相对高度和高度(从柔性或静态)。因此,如果您希望它以您自己的方式拉伸,您需要满足这些约束。
    • 粘的 :这对于页眉和页脚是理想的,但仍将在滚动条区域内。通常用于多个部分。
    • 重叠内容 :这是完全正常的,您的页眉和页脚没有纯色背景,将其设置为白色,将按预期工作。

    为了达到你想要的效果,为了让滚动条刚好出现在页眉和页脚之间,你可以添加一些普通的CSS。运行下面的代码片段来查看它。基本上只是一个灵活的布局。

    我也更新了您的示例: https://codepen.io/mohamedhmansour/pen/rQqqvP

    let { DetailsList, Fabric, ScrollablePane, ScrollbarVisibility } = window.Fabric;
    
    function Content() {
      const items = [...Array(500).keys()].map(i => ({key: i, text: `Item ${i}`}));
      
      return (
        <ScrollablePane  scrollbarVisibility={ScrollbarVisibility.auto}> 
          <DetailsList items={items} />
        </ScrollablePane>
      );
    }
    
    ReactDOM.render( 
      <Fabric className='wrapper'>
        <div className='header'>Header</div>
        <div className='main'>
          <Content />
        </div>
        <div className='footer'>Footer</div>
      </Fabric>,
      document.getElementById('content')
    );
    .wrapper {
      display: flex;
      flex-direction: column;
      width: 100%;
      position: absolute;
      top: 0;
      bottom: 0;
    }
    
    .main {
      flex: 1;
      position: relative;
    }
    
    
    .header, .footer {
      background: black;
      color: white;
      padding: 10px;
    }
    <script src="//unpkg.com/react@16/umd/react.development.js"></script>
    <script src="//unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
    <!-- could point to local version -->
    <script src="//unpkg.com/office-ui-fabric-react/dist/office-ui-fabric-react.min.js"></script>
    
    <div id='content'></div>