Skip to content

Commit

Permalink
feat(Shell): support fixedHeader&Navigation fixed mode
Browse files Browse the repository at this point in the history
  • Loading branch information
youluna committed Apr 1, 2020
1 parent 6825b66 commit 2c9eb2c
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 30 deletions.
14 changes: 6 additions & 8 deletions src/shell/base.jsx
Expand Up @@ -25,12 +25,17 @@ export default function Base(props) {
* @param {Boolean} collapse 弹层是否显示
*/
onCollapseChange: PropTypes.func,
/**
* 是否固定,仅对 Shell.Navigation Shell.ToolDock 生效
*/
fixed: PropTypes.bool,
};

static defaultProps = {
prefix: 'next-',
component: 'div',
onCollapseChange: () => {},
fixed: false,
};

static childContextTypes = {
Expand Down Expand Up @@ -61,7 +66,7 @@ export default function Base(props) {
...others
} = this.props;

let Tag = component;
const Tag = component;

const cls = classnames({
[`${prefix}shell-${componentName.toLowerCase()}`]: true,
Expand All @@ -87,13 +92,6 @@ export default function Base(props) {
return children;
}

if (
['ToolDock'].indexOf(componentName) > -1 ||
(componentName === 'Navigation' && direction === 'ver')
) {
Tag = 'aside';
}

return (
<Tag className={cls} {...others}>
{newChildren}
Expand Down
22 changes: 22 additions & 0 deletions src/shell/main.scss
Expand Up @@ -42,6 +42,11 @@
margin-left: 10px;
}

&#{$shell-prefix}-fixed-header {
position: sticky;
top: 0;
}

#{$shell-prefix}-navigation {
flex: 1;
display: flex;
Expand Down Expand Up @@ -95,6 +100,23 @@
}
}

.#{$css-prefix}aside-navigation,
.#{$css-prefix}aside-tooldock {
display: flex;
&.fixed {
position: fixed;
top: 0;
bottom: 0;
}
}

.#{$css-prefix}aside-navigation.fixed {
left: 0;
}
.#{$css-prefix}aside-tooldock.fixed {
right: 0;
}

&-aside {
transition: all .2s $motion-ease;

Expand Down
142 changes: 121 additions & 21 deletions src/shell/shell.jsx
Expand Up @@ -4,10 +4,9 @@ import PropTypes from 'prop-types';
import { polyfill } from 'react-lifecycles-compat';
import ConfigProvider from '../config-provider';
import Icon from '../icon';
import { KEYCODE } from '../util';
import { KEYCODE, dom } from '../util';

import { isBoolean, getCollapseMap } from './util';

/**
* Shell
*/
Expand All @@ -31,12 +30,17 @@ export default function ShellBase(props) {
* @enumdesc 浅色, 深色, 主题色
*/
type: PropTypes.oneOf(['light', 'dark', 'brand']),
/**
* 是否固定 header, 不支持 IE11
*/
fixedHeader: PropTypes.bool,
};

static defaultProps = {
prefix: 'next-',
device: 'desktop',
type: 'light',
fixedHeader: false,
};

constructor(props) {
Expand Down Expand Up @@ -67,6 +71,10 @@ export default function ShellBase(props) {
return {};
}

componentDidMount() {
this.checkFixed();
}

componentDidUpdate(prevProps) {
if (prevProps.device !== this.props.device) {
const deviceMapBefore = getCollapseMap(prevProps.device);
Expand All @@ -84,8 +92,41 @@ export default function ShellBase(props) {
}
});
}

setTimeout(() => {
// 如果左侧边栏固定
this.checkFixed();
}, 201);
}

checkFixed = () => {
let headerHeight;
if (
this.headerRef &&
(this.navigationFixed || this.toolDockFixed)
) {
headerHeight = dom.getStyle(this.headerRef, 'height');
}

if (this.navigationFixed) {
const style = {};
style.marginLeft = dom.getStyle(this.navRef, 'width');
dom.addClass(this.navRef, 'fixed');
headerHeight &&
dom.setStyle(this.navRef, { top: headerHeight });
dom.setStyle(this.localNavRef || this.submainRef, style);
}

if (this.toolDockFixed) {
const style = {};
style.marginRight = dom.getStyle(this.toolDockRef, 'width');
dom.addClass(this.toolDockRef, 'fixed');
headerHeight &&
dom.setStyle(this.toolDockRef, { top: headerHeight });
dom.setStyle(this.localNavRef || this.submainRef, style);
}
};

setChildCollapse = (child, mark) => {
const { device, collapseMap, controll } = this.state;
const { collapse } = child.props;
Expand Down Expand Up @@ -197,8 +238,34 @@ export default function ShellBase(props) {
this.toggleAside(mark, props, e);
};

saveHeaderRef = ref => {
this.headerRef = ref;
};
saveLocalNavRef = ref => {
this.localNavRef = ref;
};

saveNavRef = ref => {
this.navRef = ref;
};

saveSubmainRef = ref => {
this.submainRef = ref;
};

saveToolDockRef = ref => {
this.toolDockRef = ref;
};

renderShell = props => {
const { prefix, children, className, type, ...others } = props;
const {
prefix,
children,
className,
type,
fixedHeader,
...others
} = props;

const { device } = this.state;

Expand Down Expand Up @@ -239,6 +306,7 @@ export default function ShellBase(props) {
layout[mark] = [];
}

this.toolDockFixed = child.props.fixed;
const childT = this.setChildCollapse(child, mark);
layout[mark] = childT;

Expand All @@ -262,7 +330,7 @@ export default function ShellBase(props) {
}

needNavigationTrigger = true;

this.navigationFixed = child.props.fixed;
const childN = this.setChildCollapse(
child,
mark
Expand All @@ -278,6 +346,7 @@ export default function ShellBase(props) {

const headerCls = classnames({
[`${prefix}shell-header`]: true,
[`${prefix}shell-fixed-header`]: fixedHeader,
});

const mainCls = classnames({
Expand All @@ -292,6 +361,14 @@ export default function ShellBase(props) {
[`${prefix}shell-aside`]: true,
});

const toolDockCls = classnames({
[`${prefix}aside-tooldock`]: true,
});

const navigationCls = classnames({
[`${prefix}aside-navigation`]: true,
});

if (hasToolDock) {
if (device === 'phone') {
needDockTrigger = true;
Expand Down Expand Up @@ -437,7 +514,11 @@ export default function ShellBase(props) {
});

innerArr.push(
<aside key="localnavigation" className={localNavCls}>
<aside
key="localnavigation"
className={localNavCls}
ref={this.saveLocalNavRef}
>
{React.cloneElement(layout.LocalNavigation, {}, [
<div
key="wrapper"
Expand All @@ -453,7 +534,11 @@ export default function ShellBase(props) {

if (layout.content) {
innerArr.push(
<section key="submain" className={submainCls}>
<section
key="submain"
className={submainCls}
ref={this.saveSubmainRef}
>
{layout.content}
</section>
);
Expand Down Expand Up @@ -513,7 +598,11 @@ export default function ShellBase(props) {
// 按照dom结构, arr 包括 header Navigation ToolDock 和 innerArr
if (Object.keys(layout.header).length > 0) {
headerDom = (
<header key="header" className={headerCls}>
<header
key="header"
className={headerCls}
ref={this.saveHeaderRef}
>
{layout.header.Branding}
{layout.header.Navigation}
{layout.header.Action}
Expand All @@ -523,13 +612,18 @@ export default function ShellBase(props) {

layout.Navigation &&
contentArr.push(
React.cloneElement(layout.Navigation, {
className: classnames(
asideCls,
layout.Navigation.props.className
),
key: 'navigation',
})
<aside
key="navigation"
className={navigationCls}
ref={this.saveNavRef}
>
{React.cloneElement(layout.Navigation, {
className: classnames(
asideCls,
layout.Navigation.props.className
),
})}
</aside>
);

// const contentArea = innerArr.length > 0
Expand All @@ -543,13 +637,19 @@ export default function ShellBase(props) {

layout.ToolDock &&
contentArr.push(
React.cloneElement(layout.ToolDock, {
className: classnames(
asideCls,
layout.ToolDock.props.className
),
key: 'tooldock',
})
<aside
key="tooldock"
className={toolDockCls}
ref={this.saveToolDockRef}
>
{React.cloneElement(layout.ToolDock, {
className: classnames(
asideCls,
layout.ToolDock.props.className
),
key: 'tooldock',
})}
</aside>
);

const cls = classnames({
Expand Down
2 changes: 1 addition & 1 deletion src/util/dom.js
Expand Up @@ -150,7 +150,7 @@ function _getComputedStyle(node) {
: {};
}

const PIXEL_PATTERN = /margin|padding|width|height|max|min|offset|size/i;
const PIXEL_PATTERN = /margin|padding|width|height|max|min|offset|size|top/i;
const removePixel = { left: 1, top: 1, right: 1, bottom: 1 };

/**
Expand Down
3 changes: 3 additions & 0 deletions types/shell/index.d.ts
Expand Up @@ -7,6 +7,7 @@ export interface ShellProps extends HTMLAttributes<HTMLElement>, CommonProps {
*/
device?: 'tablet' | 'desktop' | 'phone';
type?: 'light' | 'dark' | 'brand';
fixedHeader?: boolean;
}

export interface ShellCommonProps extends HTMLAttributes<HTMLElement>, CommonProps {
Expand All @@ -17,6 +18,7 @@ export interface ShellNavigationProps extends ShellCommonProps {
collapse?: boolean;
direction?: 'hoz' | 'ver';
align?: 'left' | 'right' | 'center';
fixed?: boolean;
onCollapseChange?: (collapse?: boolean) => {};
}

Expand All @@ -27,6 +29,7 @@ export interface ShellLocalNavigationProps extends ShellCommonProps {

export interface ShellToolDockProps extends ShellCommonProps {
collapse?: boolean;
fixed?: boolean;
onCollapseChange?: (collapse?: boolean) => {};
}

Expand Down

0 comments on commit 2c9eb2c

Please sign in to comment.