Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

[MM-27305] Card Component Refactor for smoothness #6172

Merged
merged 2 commits into from
Aug 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion components/card/__snapshots__/card.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ exports[`components/card/card should match snapshot 1`] = `
key=".1"
>
<div
className="Card__body"
className="Card__body expanding"
onTransitionEnd={[Function]}
style={
Object {
"height": "",
Expand All @@ -35,3 +36,43 @@ exports[`components/card/card should match snapshot 1`] = `
</div>
</Card>
`;

exports[`components/card/card should match snapshot when expanded 1`] = `
<Card
expanded={true}
>
<div
className="Card expanded"
>
<CardHeader
expanded={true}
key=".0"
>
<div
className="Card__header expanded"
>
Header Test
<hr
className="Card__hr"
/>
</div>
</CardHeader>
<CardBody
expanded={true}
key=".1"
>
<div
className="Card__body expanded expanding"
onTransitionEnd={[Function]}
style={
Object {
"height": 0,
}
}
>
Body Test
</div>
</CardBody>
</div>
</Card>
`;
20 changes: 14 additions & 6 deletions components/card/card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,29 @@
}

.Card__header {
hr.Card__hr {
margin: 0 12px;
border-color: rgba(var(--center-channel-color-rgb), 0.08);
}
}

.Card__body {
overflow: hidden;
height: 0;
margin: 0 12px;

transition-duration: 0.3s;
transition-timing-function: ease-in-out;
transition-property: height, margin;
&.expanding {
transition-duration: 0.3s;
transition-timing-function: ease-in-out;
transition-property: height, margin;
}

&.expanded {
margin: 0 12px 12px 12px;
padding-top: 12px;
border-top: 1px solid rgba(var(--center-channel-color-rgb), 0.08);
margin: 12px;
}

&.expanded:not(.expanding) {
height: auto;
}
}

Expand Down
27 changes: 13 additions & 14 deletions components/card/card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,27 @@ describe('components/card/card', () => {
test('should match snapshot', () => {
const wrapper = mount(
<Card {...baseProps}>
<Card.Header {...baseProps}>{'Header Test'}</Card.Header>
<Card.Body {...baseProps}>{'Body Test'}</Card.Body>
<Card.Header>{'Header Test'}</Card.Header>
<Card.Body>{'Body Test'}</Card.Body>
</Card>
);

expect(wrapper).toMatchSnapshot();
});

test('should have a height based on content when expanded', () => {
test('should match snapshot when expanded', () => {
const props = {
...baseProps,
expanded: true,
};

const wrapper = mount(
<Card.Body {...baseProps}>
{'Body Test'}
{'Slightly Larger Body Text'}
</Card.Body>
<Card {...props}>
<Card.Header>{'Header Test'}</Card.Header>
<Card.Body>{'Body Test'}</Card.Body>
</Card>
);

expect(wrapper.find('.Card__body').prop('style')).toHaveProperty('height', '');

wrapper.setProps({expanded: true});
expect(wrapper.find('.Card__body').prop('style')).not.toHaveProperty('height', '');

wrapper.setProps({expanded: false});
expect(wrapper.find('.Card__body').prop('style')).toHaveProperty('height', '');
expect(wrapper).toMatchSnapshot();
});
});
37 changes: 22 additions & 15 deletions components/card/card_body.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React, {useState, useEffect, useRef} from 'react';
import React, {useState, useEffect} from 'react';
import classNames from 'classnames';

import './card.scss';

export default function CardBody(props: {expanded?: boolean; children: React.ReactNode}) {
const card = useRef<HTMLDivElement>(null);
const [height, setHeight] = useState<number | undefined>(0);
const [height, setHeight] = useState(0);
const [expanding, setExpanding] = useState(false);
const [expanded, setExpanded] = useState(false);

let hasListener = false;
const onChange = () => setHeight(card.current?.scrollHeight);
const stopExpanding = () => setExpanding(false);

useEffect(() => {
if (hasListener) {
window.removeEventListener('resize', onChange);
} else {
window.addEventListener('resize', onChange);
hasListener = true;
const card = (node: HTMLDivElement) => {
if (node && node.children) {
setHeight(Array.from(node.children).map((child) => child.scrollHeight).reduce((a, b) => a + b, 0));
}
}, []);
};

useEffect(() => {
onChange();
setExpanding(true);
if (props.expanded) {
setExpanded(true);
}
}, [props.expanded]);

useEffect(() => {
if (!props.expanded) {
setExpanded(false);
}
}, [expanding]);

return (
<div
ref={card}
style={{
height: props.expanded ? height : '',
height: (expanding && expanded) ? height : '',
}}
className={classNames('Card__body', {expanded: props.expanded})}
className={classNames('Card__body', {expanded, expanding})}
onTransitionEnd={stopExpanding}
>
{props.children}
</div>
Expand Down
1 change: 1 addition & 0 deletions components/card/card_header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const CardHeader: React.FC<Props> = (props: Props) => {
return (
<div className={classNames('Card__header', {expanded: props.expanded})}>
{props.children}
{props.expanded && <hr className='Card__hr'/>}
</div>
);
};
Expand Down
11 changes: 6 additions & 5 deletions components/next_steps_view/next_steps_view.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
height: 100%;
width: 100%;
transition: left 0.5s ease-in;
overflow-y: auto;
overflow-x: hidden;
display: flex;
flex-direction: column;
}

.NextStepsView__mainView {
Expand Down Expand Up @@ -65,6 +69,7 @@
.NextStepsView__header {
padding: 32px 40px 24px 40px;
display: flex;
flex-grow: 0;
}

.NextStepsView__header-headerText {
Expand Down Expand Up @@ -92,6 +97,7 @@
.NextStepsView__body {
display: flex;
height: 100%;
flex-grow: 1;
}

.NextStepsView__body-main {
Expand Down Expand Up @@ -461,11 +467,6 @@
.NextStepsView__body {
height: auto;
}

.NextStepsView__viewWrapper {
overflow-y: auto;
overflow-x: hidden;
}
}

@media screen and (max-width: 1020px) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ exports[`components/next_steps_view/steps/complete_profile_step should match sna
/>
</div>
</div>
<span
className="CompleteProfileStep__pictureError"
/>
<div
className="NextStepsView__wizardButtons"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

.PictureSelector {
margin-top: 12px;
min-height: 125px;
}
}

Expand Down Expand Up @@ -50,7 +49,6 @@
line-height: 16px;
color: var(--error-text);
padding: 0 40px;
min-height: 16px;

> span {
margin-left: 4px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,28 +134,17 @@ export default class CompleteProfileStep extends React.PureComponent<Props, Stat
/>
</div>
</div>
<span className='CompleteProfileStep__pictureError'>
{this.state.profilePictureError && (
<>
<i className='icon icon-alert-outline'/>
<FormattedMarkdownMessage
id='next_steps_view.complete_profile_step.pictureError'
defaultMessage='Photos must be in BMP, JPG or PNG format. Maximum file size is {max}.'
values={{max: Utils.fileSizeToString(this.props.maxFileSize)}}
/>
</>
)}
</span>
<div className='NextStepsView__wizardButtons'>
{/* <button
className='NextStepsView__button cancel'
onClick={this.onSkip}
>
<FormattedMessage
id='next_steps_view.skipForNow'
defaultMessage='Skip for now'
{this.state.profilePictureError &&
<span className='CompleteProfileStep__pictureError'>
<i className='icon icon-alert-outline'/>
<FormattedMarkdownMessage
id='next_steps_view.complete_profile_step.pictureError'
defaultMessage='Photos must be in BMP, JPG or PNG format. Maximum file size is {max}.'
values={{max: Utils.fileSizeToString(this.props.maxFileSize)}}
/>
</button> */}
</span>
}
<div className='NextStepsView__wizardButtons'>
<button
className={classNames('NextStepsView__button confirm', {disabled: this.isFinishDisabled()})}
onClick={this.onFinish}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,53 +71,6 @@
}
}

.InviteMembersStep__profilePicture {
flex-grow: 0;

.PictureSelector {
margin-top: 12px;
min-height: 125px;
}
}

.InviteMembersStep__fullName {
margin-left: 64px;
flex-grow: 0.75;
max-width: 600px;

.Input {
font-size: 14px;
line-height: 38px;
padding: 0 16px;
}

.Input_legend {
margin-left: 12px;
}

.Input_container {
margin-top: 28px;
}
}

.InviteMembersStep__pictureError {
font-size: 12px;
line-height: 16px;
color: var(--error-text);
padding: 0 40px;
min-height: 16px;

> span {
margin-left: 4px;
}

i {
font-size: 14px;
vertical-align: middle;
margin-top: -2px;
}
}

.InviteMembersStep__send {
display: flex;
margin-top: 8px;
Expand Down Expand Up @@ -210,14 +163,4 @@
flex-direction: column;
padding: 4px 12px 24px 12px;
}

.InviteMembersStep__fullName {
margin-left: 0;
margin-top: 32px;
max-width: unset;

.Input_container {
margin-top: 20px;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ exports[`components/next_steps_view/steps/team_profile_step should match snapsho
/>
</div>
</div>
<span
className="TeamProfileStep__pictureError"
/>
<div
className="NextStepsView__wizardButtons"
>
Expand Down
Loading