Layout 支持 bodyClassName 和 boxed 属性

This commit is contained in:
liaoxuezhi 2019-08-29 11:39:47 +08:00
parent e05fe77352
commit 9c8e205090
2 changed files with 162 additions and 111 deletions

View File

@ -26,6 +26,12 @@ body {
display: block;
}
&--boxed {
margin-right: auto;
margin-left: auto;
// box-shadow: 0 0 30px rgba(0, 0, 0, 0.3);
}
.#{$ns}Layout-header {
background: $Layout-header-bg;
box-shadow: $Layout-header-boxShadow;
@ -184,8 +190,71 @@ body {
}
}
@include media-breakpoint-down(sm) {
.#{$ns}Layout {
// Layout 层没有出现滚动条件导致移动端无法响应固定顶部/底部效果
// overflow-x: hidden;
}
.#{$ns}Layout-content {
transition: transform 0.2s ease;
}
.#{$ns}Layout-aside {
display: none;
.#{$ns}Layout--offScreen & {
position: fixed;
top: px2rem(50px);
bottom: 0;
width: $Layout--offscreen-width;
display: block !important;
visibility: visible;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
z-index: 1010;
}
}
.#{$ns}Layout-headerBar {
display: none;
}
.#{$ns}Layout--offScreen {
.#{$ns}Layout-content,
.#{$ns}Layout-footer {
background-color: $body-bg;
transition: transform 0.2s ease;
backface-visibility: hidden;
transform: translate3d($Layout--offscreen-width, 0px, 0px);
overflow: hidden;
position: fixed;
width: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1015;
padding-top: px2rem(50px);
}
}
}
@include media-breakpoint-up(md) {
.#{$ns}Layout {
&--boxed {
width: px2rem(750px);
&.#{$ns}Layout--headerFixed .#{$ns}Layout-header {
width: px2rem(750px);
}
}
&-brand,
&-brandBar,
&-aside {
@ -415,53 +484,28 @@ body {
}
}
@include media-breakpoint-down(sm) {
@include media-breakpoint-up(lg) {
.#{$ns}Layout {
// Layout 层没有出现滚动条件导致移动端无法响应固定顶部/底部效果
// overflow-x: hidden;
}
&--boxed {
width: px2rem(970px);
.#{$ns}Layout-content {
transition: transform 0.2s ease;
}
.#{$ns}Layout-aside {
display: none;
.#{$ns}Layout--offScreen & {
position: fixed;
top: px2rem(50px);
bottom: 0;
width: $Layout--offscreen-width;
display: block !important;
visibility: visible;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
z-index: 1010;
}
}
.#{$ns}Layout-headerBar {
display: none;
}
.#{$ns}Layout--offScreen {
.#{$ns}Layout-content,
.#{$ns}Layout-footer {
background-color: $body-bg;
transition: transform 0.2s ease;
backface-visibility: hidden;
transform: translate3d($Layout--offscreen-width, 0px, 0px);
overflow: hidden;
position: fixed;
width: 100%;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1015;
padding-top: px2rem(50px);
&.#{$ns}Layout--headerFixed .#{$ns}Layout-header {
width: px2rem(970px);
}
}
}
}
@include media-breakpoint-up(xl) {
.#{$ns}Layout {
&--boxed {
width: px2rem(1170px);
&.#{$ns}Layout--headerFixed .#{$ns}Layout-header {
width: px2rem(1170px);
}
}
}
}

View File

@ -33,78 +33,85 @@ interface LayoutProps {
classPrefix: string;
classnames: ClassNamesFn;
size?: 'sm' | 'base' | 'md' | 'lg';
children?: React.ReactNode;
bodyClassName?: string;
}
export class Layout extends React.Component<LayoutProps, any> {
static defaultProps = {
asideWide: false,
asideFixed: true,
asideClassName: '',
headerFixed: true,
offScreen: false,
footer: false,
};
function Layout({
header,
aside,
asideClassName,
children,
className,
contentClassName,
folded,
asideFixed,
headerFixed,
footer,
offScreen,
size,
boxed,
classnames: cx,
bodyClassName
}:LayoutProps) {
let body = <div className={cx(`Layout-body`, contentClassName)}>{children}</div>;
render() {
const {
header,
aside,
asideClassName,
children,
className,
contentClassName,
folded,
asideFixed,
headerFixed,
footer,
offScreen,
size,
boxed,
classnames: cx,
} = this.props;
let body = <div className={cx(`Layout-body`, contentClassName)}>{children}</div>;
if (aside) {
body = (
<div className={cx('Layout-content')} role="main">
{body}
</div>
);
}
return (
<div
className={cx(`Layout`, className, {
'Layout--boxed': boxed,
'Layout--withAside': !!aside,
'Layout--headerFixed': header ? headerFixed : false,
'Layout--asideFixed': aside ? asideFixed : false,
'Layout--folded': folded,
'Layout--offScreen': offScreen,
[`Layout--${size}`]: size,
'Layout--noFooter': !footer,
})}
>
{header ? <div className={cx('Layout-header')}>{header}</div> : null}
{aside ? (
<div className={cx(`Layout-aside`, asideClassName)}>
<div className={cx('Layout-asideWrap')}>
<div id="asideInner" className={cx('Layout-asideInner')}>
{aside}
</div>
</div>
</div>
) : null}
if (aside) {
body = (
<div className={cx('Layout-content')} role="main">
{body}
{footer ? (
<footer className={cx('Layout-footer')} role="footer">
{footer}
</footer>
) : null}
</div>
);
}
React.useEffect(() => {
bodyClassName && document.body.classList.add(bodyClassName);
return () => {
bodyClassName && document.body.classList.remove(bodyClassName)
};
}, [bodyClassName]);
return (
<div
className={cx(`Layout`, className, {
'Layout--boxed': boxed,
'Layout--withAside': !!aside,
'Layout--headerFixed': header ? headerFixed : false,
'Layout--asideFixed': aside ? asideFixed : false,
'Layout--folded': folded,
'Layout--offScreen': offScreen,
[`Layout--${size}`]: size,
'Layout--noFooter': !footer,
})}
>
{header ? <div className={cx('Layout-header')}>{header}</div> : null}
{aside ? (
<div className={cx(`Layout-aside`, asideClassName)}>
<div className={cx('Layout-asideWrap')}>
<div id="asideInner" className={cx('Layout-asideInner')}>
{aside}
</div>
</div>
</div>
) : null}
{body}
{footer ? (
<footer className={cx('Layout-footer')} role="footer">
{footer}
</footer>
) : null}
</div>
);
}
export default themeable(Layout);
Layout.defaultProps = {
// asideWide: false,
asideFixed: true,
asideClassName: '',
headerFixed: true,
offScreen: false,
footer: false,
};
export default themeable(Layout);