Feature 2.6 (#4429)

* new Layout Component (#4087)

* change Anchor type

* new Layout

* Component update && add snap

* Revert "new Layout Component" (#4131)

* add Layout (#4169)

* add Layout

* update

* fix snapshot

* Improve layout component

1. update demo code
2. drop `position` of Sider
3. improve demo style
This commit is contained in:
偏右 2016-12-30 21:41:28 +08:00 committed by GitHub
parent c3982b02aa
commit 0062867274
22 changed files with 1320 additions and 5 deletions

View File

@ -1,6 +1,6 @@
---
category: Components
type: Navigation
type: Other
cols: 2
title: Anchor
---

View File

@ -2,7 +2,7 @@
category: Components
subtitle: 锚点
cols: 2
type: Navigation
type: Other
title: Anchor
---

View File

@ -2,6 +2,7 @@ import React from 'react';
import { cloneElement } from 'react';
import warning from '../_util/warning';
import BreadcrumbItem from './BreadcrumbItem';
import classNames from 'classnames';
export interface BreadcrumbProps {
prefixCls?: string;
@ -10,6 +11,7 @@ export interface BreadcrumbProps {
separator?: string | React.ReactNode;
itemRender?: (route: any, params: any, routes: Array<any>, paths: Array<string>) => React.ReactNode;
style?: React.CSSProperties;
className?: string;
};
function getBreadcrumbName(route, params) {
@ -63,7 +65,10 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
render() {
let crumbs;
const { separator, prefixCls, routes, params = {}, children, itemRender = defaultItemRender } = this.props;
const {
separator, prefixCls, style, className, routes, params = {},
children, itemRender = defaultItemRender,
} = this.props;
if (routes && routes.length > 0) {
const paths: string[] = [];
crumbs = routes.map((route) => {
@ -93,7 +98,7 @@ export default class Breadcrumb extends React.Component<BreadcrumbProps, any> {
});
}
return (
<div className={prefixCls}>
<div className={classNames(className, prefixCls)} style={style}>
{crumbs}
</div>
);

View File

@ -49,6 +49,8 @@ export { default as Input } from './input';
export { default as InputNumber } from './input-number';
export { default as Layout } from './layout';
export { default as LocaleProvider } from './locale-provider';
export { default as message } from './message';

102
components/layout/Sider.tsx Normal file
View File

@ -0,0 +1,102 @@
import React from 'react';
import classNames from 'classnames';
import omit from 'omit.js';
import Icon from '../icon';
export interface SiderProps {
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
collapsible?: boolean;
collapsed?: boolean;
defaultCollapsed?: boolean;
onCollapse?: (collapsed: boolean) => void;
trigger?: React.ReactNode;
width?: number | string;
collapsedWidth?: number;
}
export default class Sider extends React.Component<SiderProps, any> {
static defaultProps = {
prefixCls: 'ant-layout-sider',
collapsible: false,
defaultCollapsed: false,
width: 200,
collapsedWidth: 64,
style: {},
};
constructor(props) {
super(props);
let collapsed;
if ('collapsed' in props) {
collapsed = props.collapsed;
} else {
collapsed = props.defaultCollapsed;
}
this.state = {
collapsed,
};
}
componentWillReceiveProps(nextProps) {
if ('collapsed' in nextProps) {
this.setState({
collapsed: nextProps.collapsed,
});
}
}
setCollapsed = (collapsed) => {
if (!('collapsed' in this.props)) {
this.setState({
collapsed,
});
}
const { onCollapse } = this.props;
if (onCollapse) {
onCollapse(collapsed);
}
}
toggle = () => {
const collapsed = !this.state.collapsed;
this.setCollapsed(collapsed);
}
render() {
const {
prefixCls, className, collapsible, trigger, style, width, collapsedWidth,
...others,
} = this.props;
const divProps = omit(others, ['collapsed', 'defaultCollapsed', 'onCollapse']);
const siderCls = classNames(className, prefixCls, {
[`${prefixCls}-collapsed`]: !!this.state.collapsed,
[`${prefixCls}-has-trigger`]: !!trigger,
});
const divStyle = {
...style,
flex: `0 0 ${this.state.collapsed ? collapsedWidth : width}px`,
};
const iconObj = {
'expanded': <Icon type="left" />,
'collapsed': <Icon type="right" />,
};
const status = this.state.collapsed ? 'collapsed' : 'expanded';
const defaultTrigger = iconObj[status];
const triggerDom = (
trigger !== null ?
(<div className={`${prefixCls}-trigger`} onClick={this.toggle}>
{trigger || defaultTrigger}
</div>)
: null
);
return (
<div className={siderCls} {...divProps} style={divStyle}>
{this.props.children}
{collapsible && triggerDom}
</div>
);
}
}

View File

@ -0,0 +1,505 @@
exports[`test renders ./components/layout/demo/custom-trigger.md correctly 1`] = `
<div
class="ant-layout-demo-custom ant-layout">
<div
class="ant-layout-sider"
style="flex:0 0 200px;">
<div
class="logo" />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
role="menu"
tabindex="0">
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-user" />
<span
class="nav-text">
nav 1
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-video-camera" />
<span
class="nav-text">
nav 2
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-upload" />
<span
class="nav-text">
nav 3
</span>
</li>
</ul>
</div>
<div
class="ant-layout">
<div
class="ant-layout-header">
<div
class="nav">
<i
class="anticon anticon-menu-fold trigger" />
</div>
</div>
<div
class="content ant-layout-content">
content
</div>
</div>
</div>
`;
exports[`test renders ./components/layout/demo/demo.md correctly 1`] = `
<div
class="ant-layout"
style="color:#fff;background-color:#ededed;background-size:50px 50px;background-image:linear-gradient(45deg, rgba(255, 255, 255, .7) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .7) 50%, rgba(255, 255, 255, .7) 75%, transparent 75%, transparent);">
<div
class="ant-layout-header"
style="color:#fff;background:rgba(16, 142, 233, 0.5);">
Header
</div>
<div
class="ant-layout"
style="color:#fff;background-color:#ededed;background-size:50px 50px;background-image:linear-gradient(-45deg, rgba(255, 255, 255, .7) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .7) 50%, rgba(255, 255, 255, .7) 75%, transparent 75%, transparent);">
<div
class="ant-layout-sider"
style="color:#fff;background:rgba(16, 142, 233, 0.9);flex:0 0 200px;">
Sider
</div>
<div
class="ant-layout-content"
style="color:#fff;background:rgba(16, 142, 233, 0.7);">
Content
</div>
</div>
<div
class="ant-layout-footer"
style="color:#fff;background:rgba(16, 142, 233, 0.5);">
Footer
</div>
</div>
`;
exports[`test renders ./components/layout/demo/side.md correctly 1`] = `
<div
class="ant-layout-demo-side ant-layout">
<div
class="ant-layout-sider"
style="flex:0 0 200px;">
<div
class="logo" />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-dark ant-menu-root"
role="menu"
tabindex="0">
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-user" />
<span
class="nav-text">
nav 1
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-video-camera" />
<span
class="nav-text">
nav 2
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-upload" />
<span
class="nav-text">
nav 3
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-user" />
<span
class="nav-text">
nav 4
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-heart-o" />
<span
class="nav-text">
nav 5
</span>
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:24px;">
<i
class="anticon anticon-team" />
<span
class="nav-text">
nav 6
</span>
</li>
</ul>
<div
class="ant-layout-sider-trigger">
<i
class="anticon anticon-left" />
</div>
</div>
<div
class="ant-layout">
<div
class="ant-layout-header">
<div
class="nav" />
</div>
<div
class="main ant-layout-content">
<div
class="breadcrumb">
<div
class="ant-breadcrumb">
<span>
<span
class="ant-breadcrumb-link">
Home
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
List
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
App
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
</div>
</div>
<div>
content
</div>
</div>
<div
class="footer ant-layout-footer">
Ant Design ©2016 Created by Ant UED
</div>
</div>
</div>
`;
exports[`test renders ./components/layout/demo/top.md correctly 1`] = `
<div
class="ant-layout-demo-top ant-layout">
<div
class="ant-layout-header">
<div
class="logo" />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
role="menu"
style="line-height:64px;"
tabindex="0">
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem">
nav 1
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
role="menuitem">
nav 2
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem">
nav 3
</li>
</ul>
</div>
<div
class="ant-layout-content">
<div
class="breadcrumb">
<div
class="ant-breadcrumb">
<span>
<span
class="ant-breadcrumb-link">
Home
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
List
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
App
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
</div>
</div>
<div
class="content">
content
</div>
</div>
<div
class="footer ant-layout-footer">
Ant Design ©2016 Created by Ant UED
</div>
</div>
`;
exports[`test renders ./components/layout/demo/top-side.md correctly 1`] = `
<div
class="ant-layout-demo-topside ant-layout">
<div
class="header ant-layout-header">
<div>
<div
class="logo" />
<ul
aria-activedescendant=""
class="ant-menu ant-menu-horizontal ant-menu-dark ant-menu-root"
role="menu"
style="line-height:64px;"
tabindex="0">
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem">
nav 1
</li>
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
role="menuitem">
nav 2
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem">
nav 3
</li>
</ul>
</div>
<div
class="breadcrumb">
<div
class="ant-breadcrumb">
<span>
<span
class="ant-breadcrumb-link">
Home
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
List
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
<span>
<span
class="ant-breadcrumb-link">
App
</span>
<span
class="ant-breadcrumb-separator">
/
</span>
</span>
</div>
</div>
</div>
<div
class="main ant-layout">
<div
class="sider ant-layout-sider"
style="flex:0 0 200pxpx;">
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-light ant-menu-root"
role="menu"
tabindex="0">
<li
class="ant-menu-submenu-inline ant-menu-submenu-open ant-menu-submenu-selected ant-menu-submenu">
<div
aria-expanded="true"
aria-haspopup="true"
aria-owns="sub1$Menu"
class="ant-menu-submenu-title"
style="padding-left:24px;">
<span>
<i
class="anticon anticon-user" />
subnav 1
</span>
</div>
<ul
aria-activedescendant=""
class="ant-menu ant-menu-inline ant-menu-sub"
id="sub1$Menu"
role="menu">
<li
aria-selected="true"
class="ant-menu-item-selected ant-menu-item"
role="menuitem"
style="padding-left:48px;">
option1
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:48px;">
option2
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:48px;">
option3
</li>
<li
aria-selected="false"
class="ant-menu-item"
role="menuitem"
style="padding-left:48px;">
option4
</li>
</ul>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu">
<div
aria-expanded="false"
aria-haspopup="true"
aria-owns="sub2$Menu"
class="ant-menu-submenu-title"
style="padding-left:24px;">
<span>
<i
class="anticon anticon-laptop" />
subnav 2
</span>
</div>
</li>
<li
class="ant-menu-submenu-inline ant-menu-submenu">
<div
aria-expanded="false"
aria-haspopup="true"
aria-owns="sub3$Menu"
class="ant-menu-submenu-title"
style="padding-left:24px;">
<span>
<i
class="anticon anticon-notification" />
subnav 3
</span>
</div>
</li>
</ul>
</div>
<div
class="ant-layout-content">
content
</div>
</div>
<div
class="footer ant-layout-footer">
Ant Design ©2016 Created by Ant UED
</div>
</div>
`;

View File

@ -0,0 +1,3 @@
import demoTest from '../../../tests/shared/demoTest';
demoTest('layout');

View File

@ -0,0 +1,87 @@
---
order: 0
title:
zh-CN: 基本结构
en-US: Basic Structure
---
## zh-CN
典型的页面布局。
## en-US
Classic page layouts.
````jsx
import { Layout } from 'antd';
const { Header, Footer, Sider, Content } = Layout;
ReactDOM.render(
<div>
<Layout>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Layout>
<Layout>
<Header>Header</Header>
<Layout>
<Sider>Sider</Sider>
<Content>Content</Content>
</Layout>
<Footer>Footer</Footer>
</Layout>
<Layout>
<Header>Header</Header>
<Layout>
<Content>Content</Content>
<Sider position="right">Sider</Sider>
</Layout>
<Footer>Footer</Footer>
</Layout>
<Layout>
<Sider>Sider</Sider>
<Content>
<Header>Header</Header>
<Content>Content</Content>
<Footer>Footer</Footer>
</Content>
</Layout>
</div>
, mountNode);
````
<style>
#components-layout-demo-basic .code-box-demo {
text-align: center;
}
#components-layout-demo-basic .ant-layout-header,
#components-layout-demo-basic .ant-layout-footer {
background: #7dbcea;
color: #fff;
}
#components-layout-demo-basic .ant-layout-footer {
line-height: 1.5;
}
#components-layout-demo-basic .ant-layout-sider {
background: #3ba0e9;
color: #fff;
line-height: 120px;
}
#components-layout-demo-basic .ant-layout-content {
background: rgba(16, 142, 233, 1);
color: #fff;
min-height: 120px;
line-height: 120px;
}
#components-layout-demo-basic > .code-box-demo > div > .ant-layout {
margin-bottom: 48px;
}
#components-layout-demo-basic > .code-box-demo > div > .ant-layout:last-child {
margin: 0;
}
</style>

View File

@ -0,0 +1,100 @@
---
order: 4
title:
zh-CN: 自定义触发器
en-US: Custom trigger
---
## zh-CN
要使用自定义触发器,可以设置 `trigger={null}` 来隐藏默认设定。
## en-US
If you want to use a customized trigger, you can hide the default one by setting `trigger={null}`.
````jsx
import { Layout, Menu, Icon } from 'antd';
const { Header, Sider, Content } = Layout;
class SiderDemo extends React.Component {
state = {
collapsed: false,
};
toggle = () => {
this.setState({
collapsed: !this.state.collapsed,
});
}
render() {
return (
<Layout>
<Sider
trigger={null}
collapsible
collapsed={this.state.collapsed}
>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1">
<Icon type="user" />
<span className="nav-text">nav 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="video-camera" />
<span className="nav-text">nav 2</span>
</Menu.Item>
<Menu.Item key="3">
<Icon type="upload" />
<span className="nav-text">nav 3</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }}>
<Icon
className="trigger"
type={this.state.collapsed ? 'menu-unfold' : 'menu-fold'}
onClick={this.toggle}
/>
</Header>
<Content style={{ margin: '24px 16px', padding: 24, background: '#fff', minHeight: 280 }}>
Content
</Content>
</Layout>
</Layout>
);
}
}
ReactDOM.render(<SiderDemo />, mountNode);
````
````css
#components-layout-demo-custom-trigger .trigger {
font-size: 18px;
line-height: 64px;
padding: 0 16px;
cursor: pointer;
transition: color .3s;
}
#components-layout-demo-custom-trigger .trigger:hover {
color: #108ee9;
}
#components-layout-demo-custom-trigger .logo {
height: 32px;
background: #333;
border-radius: 6px;
margin: 16px;
}
#components-layout-demo-custom-trigger .ant-layout-sider-collapsed .anticon {
font-size: 16px;
}
#components-layout-demo-custom-trigger .ant-layout-sider-collapsed .nav-text {
display: none;
}
````

View File

@ -0,0 +1,103 @@
---
order: 3
title:
zh-CN: 侧边布局
en-US: Sider
---
## zh-CN
多用在两列式布局。
## en-US
Be used in the two-columns layout.
````jsx
import { Layout, Menu, Breadcrumb, Icon } from 'antd';
const { Header, Content, Footer, Sider } = Layout;
class SiderDemo extends React.Component {
state = {
collapsed: false,
};
onCollapse = (collapsed) => {
console.log(collapsed);
this.setState({ collapsed });
}
render() {
return (
<Layout>
<Sider
collapsible
collapsed={this.state.collapsed}
onCollapse={this.onCollapse}
>
<div className="logo" />
<Menu theme="dark" mode="inline" defaultSelectedKeys={['1']}>
<Menu.Item key="1">
<Icon type="user" />
<span className="nav-text">nav 1</span>
</Menu.Item>
<Menu.Item key="2">
<Icon type="video-camera" />
<span className="nav-text">nav 2</span>
</Menu.Item>
<Menu.Item key="3">
<Icon type="upload" />
<span className="nav-text">nav 3</span>
</Menu.Item>
<Menu.Item key="4">
<Icon type="user" />
<span className="nav-text">nav 4</span>
</Menu.Item>
<Menu.Item key="5">
<Icon type="heart-o" />
<span className="nav-text">nav 5</span>
</Menu.Item>
<Menu.Item key="6">
<Icon type="team" />
<span className="nav-text">nav 6</span>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Header style={{ background: '#fff', padding: 0 }} />
<Content style={{ margin: '0 16px' }}>
<Breadcrumb style={{ margin: '12px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div style={{ padding: 24, background: '#fff', minHeight: 360 }}>
content
</div>
</Content>
<Footer style={{ textAlign: 'center' }}>
Ant Design ©2016 Created by Ant UED
</Footer>
</Layout>
</Layout>
);
}
}
ReactDOM.render(<SiderDemo />, mountNode);
````
````css
#components-layout-demo-side .logo {
height: 32px;
background: #333;
border-radius: 6px;
margin: 16px;
}
#components-layout-demo-side .ant-layout-sider-collapsed .anticon {
font-size: 16px;
}
#components-layout-demo-side .ant-layout-sider-collapsed .nav-text {
display: none;
}
````

View File

@ -0,0 +1,90 @@
---
order: 2
title:
zh-CN: 顶部-侧边布局
en-US: Header-Sider
---
## zh-CN
多用在同时拥有顶部导航及侧边栏的页面。
## en-US
Be used in the page which has both the top navigation and the sidebar.
````jsx
import { Layout, Menu, Breadcrumb, Icon } from 'antd';
const { SubMenu } = Menu;
const { Header, Content, Footer, Sider } = Layout;
ReactDOM.render(
<Layout>
<Header className="header">
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
style={{ lineHeight: '64px' }}
>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>
</Menu>
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '12px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<Layout style={{ padding: '24px 0', background: '#fff' }}>
<Sider width={200}>
<Menu
mode="inline"
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
>
<SubMenu key="sub1" title={<span><Icon type="user" />subnav 1</span>}>
<Menu.Item key="1">option1</Menu.Item>
<Menu.Item key="2">option2</Menu.Item>
<Menu.Item key="3">option3</Menu.Item>
<Menu.Item key="4">option4</Menu.Item>
</SubMenu>
<SubMenu key="sub2" title={<span><Icon type="laptop" />subnav 2</span>}>
<Menu.Item key="5">option5</Menu.Item>
<Menu.Item key="6">option6</Menu.Item>
<Menu.Item key="7">option7</Menu.Item>
<Menu.Item key="8">option8</Menu.Item>
</SubMenu>
<SubMenu key="sub3" title={<span><Icon type="notification" />subnav 3</span>}>
<Menu.Item key="9">option9</Menu.Item>
<Menu.Item key="10">option10</Menu.Item>
<Menu.Item key="11">option11</Menu.Item>
<Menu.Item key="12">option12</Menu.Item>
</SubMenu>
</Menu>
</Sider>
<Content style={{ padding: '0 24px', minHeight: 280 }}>
Content
</Content>
</Layout>
</Content>
<Footer style={{ textAlign: 'center' }}>
Ant Design ©2016 Created by Ant UED
</Footer>
</Layout>
, mountNode);
````
````css
#components-layout-demo-top-side .logo {
width: 120px;
height: 31px;
background: #333;
border-radius: 6px;
margin: 16px 28px 16px 0;
float: left;
}
````

View File

@ -0,0 +1,59 @@
---
order: 1
title:
zh-CN: 上中下布局
en-US: Header-Content-Footer
---
## zh-CN
最基本的『上-中-下』布局。
## en-US
The most basic "header-content-footer" layout.
````jsx
import { Layout, Menu, Breadcrumb } from 'antd';
const { Header, Content, Footer } = Layout;
ReactDOM.render(
<Layout className="layout">
<Header>
<div className="logo" />
<Menu
theme="dark"
mode="horizontal"
defaultSelectedKeys={['2']}
style={{ lineHeight: '64px' }}
>
<Menu.Item key="1">nav 1</Menu.Item>
<Menu.Item key="2">nav 2</Menu.Item>
<Menu.Item key="3">nav 3</Menu.Item>
</Menu>
</Header>
<Content style={{ padding: '0 50px' }}>
<Breadcrumb style={{ margin: '12px 0' }}>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>List</Breadcrumb.Item>
<Breadcrumb.Item>App</Breadcrumb.Item>
</Breadcrumb>
<div style={{ background: '#fff', padding: 24, minHeight: 280 }}>Content</div>
</Content>
<Footer style={{ textAlign: 'center' }}>
Ant Design ©2016 Created by Ant UED
</Footer>
</Layout>
, mountNode);
````
````css
#components-layout-demo-top .logo {
width: 120px;
height: 31px;
background: #333;
border-radius: 6px;
margin: 16px 24px 16px 0;
float: left;
}
````

View File

@ -0,0 +1,59 @@
---
category: Components
type: Layout
cols: 1
title: Layout
---
When you are handling the overall layout of a page, this component might be helpfull.
## Overview
- `Layout`: The layout wrapper, in which `Header` `Sider` `Content` `Footer` or `Layout` itself can be nested.
- `Header`: The top layout with default style.
- `Sider`: The sidebar with default style and basic functions.
- `Content`: The content layout with default style.
- `Footer`: The bottom layout with default style.
> Base on `flex layout`, please pay attention to the [compatibility](http://caniuse.com/#search=flex).
## API
```jsx
<Layout>
<Header>header</Header>
<Layout>
<Sider>left sidebar</Sider>
<Content>main content</Content>
<Sider>right sidebar</Sider>
</Layout>
<Footer>footer</Footer>
</Layout>
```
### Layout
The wrapper.
Property | Description | Type | Default
-----|-----|-----|------
style | to custom the styles | Object | -
className | container className | string | -
> API of `Layout.Header` `Layout.Footer` `Layout.Content` is the same with `Layout`.
### Layout.Sider
The sidebar.
Property | Description | Type | Default
-----|-----|-----|------
collapsible | whether can be collapsed | Boolean | false
defaultCollapsed | to set the initial status | Boolean | false |
collapsed | to set the current status | Boolean | -
onCollapse | the callback function, can be executed when you switch the sidebar, available only `collapsible: true` | (collapsed) => {} | -
trigger | specify the customized trigger, set to null to hide the trigger | React.ReactNode or null | - |
width | width of the sidebar | Number or String | 200
collapsedWidth | width of the collapsed sidebar, available only `collapsible: true` | Number | 64
style | to custom the styles | Object | -
className | container className | string | -

View File

@ -0,0 +1,5 @@
import Layout from './layout';
import Sider from './sider';
Layout.Sider = Sider;
export default Layout;

View File

@ -0,0 +1,60 @@
---
category: Components
subtitle: 布局
type: Layout
cols: 1
title: Layout
---
可协助进行页面级整体布局。
## 概述
- `Layout`:布局容器,其下可嵌套 `Header` `Sider` `Content` `Footer``Layout` 本身。
- `Header`:顶部布局,自带默认样式。
- `Sider`:侧边栏,自带默认样式及基本功能。
- `Content`:内容部分,自带默认样式。
- `Footer`:底部布局,自带默认样式。
> 注意:采用 flex 布局实现,请注意[浏览器兼容性](http://caniuse.com/#search=flex)问题。
## API
```jsx
<Layout>
<Header>header</Header>
<Layout>
<Sider>left sidebar</Sider>
<Content>main content</Content>
<Sider>right sidebar</Sider>
</Layout>
<Footer>footer</Footer>
</Layout>
```
### Layout
布局容器。
| 参数 | 说明 | 类型 | 默认值 |
|----------|------------------------------------------|-------------|-------|
| style | 指定样式 | Object | - |
| className | 容器 className | string | - |
> `Layout.Header` `Layout.Footer` `Layout.Content` API 与 `Layout` 相同
### Layout.Sider
侧边栏。
| 参数 | 说明 | 类型 | 默认值 |
|----------|-----------------------------------------|------------|-------|
| collapsible | 是否可收起 | Boolean | false |
| defaultCollapsed | 是否默认收起 | Boolean | false |
| collapsed | 当前收起状态 | Boolean | - |
| onCollapse | 展开-收起时的回调函数,仅当 `collapsible:true` 时生效 | (collapsed) => {} | - |
| trigger | 自定义 trigger设置为 null 时隐藏 trigger | React.ReactNode or null | - |
| width | 宽度 | Number or String | 200 |
| collapsedWidth | 收缩宽度,仅当 `collapsible:true` 时生效 | Number | 64 |
| style | 指定样式 | Object | - |
| className | 容器 className | string | - |

View File

@ -0,0 +1,55 @@
import React from 'react';
import classNames from 'classnames';
export interface BasicProps {
style?: React.CSSProperties;
prefixCls?: string;
className?: string;
}
function generator(props) {
return (Basic) : any => {
return class Adapter extends React.Component<BasicProps, any> {
static Header: any;
static Footer: any;
static Content: any;
static Sider: any;
render() {
const { prefixCls } = props;
return <Basic prefixCls={prefixCls} {...this.props}/>;
}
};
};
}
class Basic extends React.Component<BasicProps, any> {
render() {
const { prefixCls, className, ...others } = this.props;
const divCls = classNames(className, prefixCls);
return (
<div className={divCls} {...others} />
);
}
}
const Layout = generator({
prefixCls: 'ant-layout',
})(Basic);
const Header = generator({
prefixCls: 'ant-layout-header',
})(Basic);
const Footer = generator({
prefixCls: 'ant-layout-footer',
})(Basic);
const Content = generator({
prefixCls: 'ant-layout-content',
})(Basic);
Layout.Header = Header;
Layout.Footer = Footer;
Layout.Content = Content;
export default Layout;

View File

@ -0,0 +1,65 @@
@import "../../style/themes/default";
@import "../../style/mixins/index";
@layout-prefix-cls: ~"@{ant-prefix}-layout";
.@{layout-prefix-cls} {
display: flex;
flex-wrap: wrap;
flex: auto;
overflow: auto;
background: @layout-body-background;
&-header,
&-footer {
flex: 1 0 100%;
}
&-header {
background: @layout-header-background;
padding: @layout-header-padding;
height: @layout-header-height;
line-height: @layout-header-height;
}
&-footer {
padding: @layout-footer-padding;
color: @text-color;
font-size: @font-size-base;
}
&-content {
flex: auto;
}
&-sider {
flex: 0 0 200px;
transition: all .3s ease;
position: relative;
background: @layout-sider-background;
&-has-trigger {
padding-bottom: @layout-trigger-height;
}
&-right {
order: 1;
}
&-collapsed {
flex: 0 0 64px;
}
&-trigger {
position: absolute;
text-align: center;
width: 100%;
bottom: 0;
cursor: pointer;
height: @layout-trigger-height;
line-height: @layout-trigger-height;
background: tint(@heading-color, 20%);
color: #fff;
}
}
}

View File

@ -0,0 +1,2 @@
import '../../style/index.less';
import './index.less';

View File

@ -178,6 +178,7 @@
.@{iconfont-css-prefix} {
min-width: 14px;
margin-right: 8px;
transition: all .3s;
}
}

View File

@ -119,10 +119,20 @@
@screen-lg-min : @screen-lg;
@screen-lg-max : (@screen-lg-min - 1);
// Layout and Grid system
// Grid system
@grid-columns : 24;
@grid-gutter-width : 0;
// Layout
@layout-body-background : #ececec;
@layout-header-background : @heading-color;
@layout-header-height : 64px;
@layout-header-padding : 0 50px;
@layout-footer-padding : 24px 50px;
@layout-sider-background : @heading-color;
@layout-content-margin : 24px;
@layout-trigger-height : 48px;
// z-index list
@zindex-affix : 10;
@zindex-back-top : 10;

View File

@ -9,3 +9,4 @@ $('dist')
// eslint-disable-next-line
console.log('`dist` directory is valid.');

View File

@ -25,3 +25,4 @@ $('lib/*/style')
// eslint-disable-next-line
console.log('`lib` directory is valid.');