Office UI Fabric的布局问题

时间:2018-11-27 18:35:18

标签: html office-ui-fabric

[EDIT:已更新,将问题重点放在重叠的问题上;还对CodePens进行了编辑] [EDIT2:已更新,以包含有关Mohamed Mansour建议的方法的详细信息]

我在设计Office UI Fabric React UI的布局时遇到困难。这是我目前拥有的布局:

enter image description here

目标是将顶部的CommandBar和标题(文本标签和搜索框)固定在顶部,DetailsList和文件按钮固定在底部,并在标题区域之后占用尽可能多的空间。 / p>

我已经成功使用ScrollablePane和两个Sticky组件将CommandBar和按钮固定在所需的位置。但是,DetailsList滚动浏览包含CommandBar和标题的顶部Sticky,并且按钮稍微覆盖在DetailsList网格的顶部:

enter image description here

我尝试使用Fabric Grid组件来布局所有部分,但没有任何区别(如果有帮助的话)。最佳布局的项目部分位于两个Sticky元素之间;如果将项目部分添加到“页眉”或“页脚粘滞”元素中,则布局是可怕的。如何确保DetailsList不会在顶部和底部组件下方滚动?

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

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

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')
);

此外,当尝试在使用嵌套自定义React组件的代码笔之外的项目中在父div中使用Flex类或在父div中定义的高度时(根据Mohamed Mansour的建议),整个DetailsList无法呈现。例如,此DOM资源管理器显示了即使在多个“主” div中设置了定义的高度并使用flex仍然仍然无法呈现DetailsList:

enter image description here

1 个答案:

答案 0 :(得分:0)

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

  • ScrollablePane :使用绝对定位,父级必须具有相对高度和高度(来自flex或static)。因此,如果您希望它以自己的方式伸展,则需要满足这些约束。
  • 粘稠:这些是页眉和页脚的理想选择,但仍位于滚动条区域内。通常用于多个部分。
  • 重叠的内容:这完全正常,您的页眉和页脚没有固定背景,将其设置为白色,即可正常使用。

要实现所需的效果,滚动条仅出现在页眉和页脚之间,可以添加一些普通的CSS。运行下面的代码片段以查看它。基本上只是弹性布局。

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

Object { model: "general.module", pk: 1, fields: { name: "General" } }
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;
}