Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panel transition abruptly snapping to the end #2200

Merged
merged 11 commits into from
Mar 19, 2023
Merged
20 changes: 20 additions & 0 deletions packages/vue-components/src/__tests__/Panels.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@ describe('NestedPanels', () => {
expect(wrapper.element).toMatchSnapshot();
});

test('transition height is correctly calculated', async () => {
const wrapper = mount(NestedPanel, {
slots: {
header: 'test header',
default: 'Some panel content\nsome other text',
},
propsData: {
preload: true,
},
attachTo: document.body,
});
const panelElement = wrapper.element.querySelector('.card-collapse');
Object.defineProperty(panelElement, 'scrollHeight', { configurable: true, value: 10 });
const bottomSwitch = wrapper.element.querySelector('.card-body > .collapse-button');
bottomSwitch.style.marginBottom = '13px';
// click on header
await wrapper.find('div.card-header').trigger('click');
expect(wrapper.element).toMatchSnapshot();
});

test('should have span.anchor when id is present', async () => {
const wrapper = mount(NestedPanel, {
propsData: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,100 @@ exports[`NestedPanels should show header when collapsed with expandHeaderless as
</div>
</div>
`;

exports[`NestedPanels transition height is correctly calculated 1`] = `
<div
class="card-container"
>
<!---->

<div
class="card expandable-card"
>
<div
class="card-header header-toggle bg-light"
>
<div
class="caret-wrapper"
>
<!---->
</div>

<div
class="header-wrapper card-title bg-light"
>
test header
</div>

<div
class="button-wrapper"
>
<button
class="collapse-button btn btn-outline-secondary"
type="button"
>
<span
aria-hidden="true"
class="collapse-icon glyphicon glyphicon-menu-down opened"
/>
</button>

<button
class="close-button btn btn-outline-secondary"
type="button"
>
<span
aria-hidden="true"
class="glyphicon glyphicon-remove"
/>
</button>

<button
class="popup-button btn btn-outline-secondary"
style="display: none;"
type="button"
>
<span
aria-hidden="true"
class="glyphicon glyphicon-new-window"
/>
</button>
</div>
</div>

<div
class="card-collapse"
style="max-height: 23px;"
>
<div
class="card-body"
>
Some panel content
some other text
<!---->

<button
class="collapse-button btn btn-outline-secondary"
style="margin-bottom: 13px;"
type="button"
>
<span
aria-hidden="true"
class="collapse-icon glyphicon glyphicon-menu-down opened"
/>
</button>
</div>

<hr
style="display: none;"
/>
</div>

<transition-stub
name="peek-read-more-fade"
>
<!---->
</transition-stub>
</div>
</div>
`;
27 changes: 24 additions & 3 deletions packages/vue-components/src/panels/PanelBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default {
} else {
// Expand panel
this.$refs.panel.style.transition = 'max-height 0.5s ease-in-out';
this.$refs.panel.style.maxHeight = `${this.$refs.panel.scrollHeight}px`;
this.$refs.panel.style.maxHeight = `${this.getMaxHeight()}px`;
}

this.localExpanded = !this.localExpanded;
Expand All @@ -174,7 +174,7 @@ export default {
DOM update (nextTick) before setting maxHeight for transition.
*/
this.$nextTick(() => {
this.$refs.panel.style.maxHeight = `${this.$refs.panel.scrollHeight}px`;
this.$refs.panel.style.maxHeight = `${this.getMaxHeight()}px`;
});
});
},
Expand All @@ -196,7 +196,28 @@ export default {
}

// For expansion transition to 'continue' after src is loaded.
this.$refs.panel.style.maxHeight = `${this.$refs.panel.scrollHeight}px`;
this.$refs.panel.style.maxHeight = `${this.getMaxHeight()}px`;
},
getMaxHeight() {
if (!this.bottomSwitchBool) {
return this.$refs.panel.scrollHeight;
}
/*
Collapse button at bottom of panel's bottom margin is not included in panel's scrollHeight.

It's bottom margin is added to the maxHeight of the panel to enable a smooth transition.
Otherwise, there would be an instant transition when reaching the end of the panel content.
*/
const bottomSwitch = document.querySelector('.card-body > .collapse-button');
if (bottomSwitch == null) {
return this.$refs.panel.scrollHeight;
}
const bottomSwitchStyle = window.getComputedStyle(bottomSwitch);
const bottomSwitchBottomMargin = parseFloat(bottomSwitchStyle.marginBottom);
if (Number.isNaN(bottomSwitchBottomMargin)) {
return this.$refs.panel.scrollHeight;
}
return this.$refs.panel.scrollHeight + bottomSwitchBottomMargin;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would creating a <div> wrapper with bottom padding instead work?

},
initPanel() {
this.$refs.panel.addEventListener('transitionend', (event) => {
Expand Down