Fix card header expansion glitch on card collapse
This commit fixes an issue where the card's header would improperly
expand to full height during card collapse, leading to a less smooth
user experience. Previously, this was caused by the indiscriminate use
of `transition: all` in the `.card__expander`, which included unwanted
properties in the transition during collapse, such as height. This is
solved by using Vue transitions to apply transition only during
expansion.
Changes:
- Introduce a new Vue component, `CardExpandAnimation`:
- Centralizes the animation process, applying the same animation to
both the card and its arrow for consistency.
- Resolves the glitch by adjusting classes exclusively during the
enter animation phase, avoiding unintended side effects during leave
animation phase.
- Adopts a Vue-idiomatic approach for transition management, improving
code readability and maintainability.
- Improves separation of concerns by isolating animation logic from
the component's core functionality, facilitating easier updates or
replacements.
- Remove unnecessary transitions to enhance code simplicity and
performance:
- Remove `transition: all` on `.card__expander`, which was identified
as the cause of the issue.
- Remove unnecessary `transition: all` on `.card`.
- Adjust transitions to specifically target and affect the transform
property (instead of `all`) to optimize animation behavior and
eliminate potential side-effects.
These changes not only fix the issue at hand but also contribute to a
more maintainable and performant codebase by clarifying animation logic
and reducing unnecessary CSS transitions.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InstructionSteps', // Define component name for empty component for Vue build and ESLint compatibility.
|
||||
// Empty component for ESLint compatibility, workaround for https://github.com/vuejs/vue-eslint-parser/issues/125.
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'InstructionSteps', // Define component name for empty component for Vue build and ESLint compatibility.
|
||||
// Empty component for ESLint compatibility, workaround for https://github.com/vuejs/vue-eslint-parser/issues/125.
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<transition name="card-expand-collapse-transition">
|
||||
<slot />
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
// Empty component for ESLint compatibility, workaround for https://github.com/vuejs/vue-eslint-parser/issues/125.
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use "@/presentation/assets/styles/main" as *;
|
||||
|
||||
.card-expand-collapse-transition-enter-active {
|
||||
transition:
|
||||
opacity 0.3s ease-in-out,
|
||||
max-height 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.card-expand-collapse-transition-enter-from {
|
||||
opacity: 0; // Fade-in
|
||||
max-height: 0; // Expand
|
||||
}
|
||||
</style>
|
||||
@@ -3,7 +3,6 @@
|
||||
ref="cardElement"
|
||||
class="card"
|
||||
:class="{
|
||||
'is-collapsed': !isExpanded,
|
||||
'is-inactive': activeCategoryId && activeCategoryId !== categoryId,
|
||||
'is-expanded': isExpanded,
|
||||
}"
|
||||
@@ -29,20 +28,26 @@
|
||||
:category-id="categoryId"
|
||||
/>
|
||||
</div>
|
||||
<div class="card__expander" @click.stop>
|
||||
<div class="card__expander__close-button">
|
||||
<FlatButton
|
||||
icon="xmark"
|
||||
@click="collapse()"
|
||||
/>
|
||||
<CardExpandTransition>
|
||||
<div
|
||||
v-show="isExpanded"
|
||||
class="card__expander"
|
||||
@click.stop
|
||||
>
|
||||
<div class="card__expander__close-button">
|
||||
<FlatButton
|
||||
icon="xmark"
|
||||
@click="collapse()"
|
||||
/>
|
||||
</div>
|
||||
<div class="card__expander__content">
|
||||
<ScriptsTree
|
||||
:category-id="categoryId"
|
||||
:has-top-padding="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card__expander__content">
|
||||
<ScriptsTree
|
||||
:category-id="categoryId"
|
||||
:has-top-padding="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardExpandTransition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -56,6 +61,7 @@ import { injectKey } from '@/presentation/injectionSymbols';
|
||||
import ScriptsTree from '@/presentation/components/Scripts/View/Tree/ScriptsTree.vue';
|
||||
import { sleep } from '@/infrastructure/Threading/AsyncSleep';
|
||||
import CardSelectionIndicator from './CardSelectionIndicator.vue';
|
||||
import CardExpandTransition from './CardExpandTransition.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@@ -63,6 +69,7 @@ export default defineComponent({
|
||||
AppIcon,
|
||||
CardSelectionIndicator,
|
||||
FlatButton,
|
||||
CardExpandTransition,
|
||||
},
|
||||
props: {
|
||||
categoryId: {
|
||||
@@ -134,8 +141,6 @@ $expanded-margin-top : 30px;
|
||||
$card-horizontal-gap : $card-gap;
|
||||
|
||||
.card {
|
||||
transition: all 0.2s ease-in-out;
|
||||
|
||||
&__inner {
|
||||
padding-top: $card-inner-padding;
|
||||
padding-right: $card-inner-padding;
|
||||
@@ -149,7 +154,7 @@ $card-horizontal-gap : $card-gap;
|
||||
width: 100%;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
transition: all 0.2s ease-in-out;
|
||||
transition: transform 0.2s ease-in-out;
|
||||
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
@@ -160,9 +165,6 @@ $card-horizontal-gap : $card-gap;
|
||||
color: $color-on-secondary;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
&:after {
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.card__inner__title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -185,7 +187,6 @@ $card-horizontal-gap : $card-gap;
|
||||
}
|
||||
}
|
||||
.card__expander {
|
||||
transition: all 0.2s ease-in-out;
|
||||
position: relative;
|
||||
background-color: $color-primary-darker;
|
||||
color: $color-on-primary;
|
||||
@@ -214,22 +215,6 @@ $card-horizontal-gap : $card-gap;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-collapsed {
|
||||
.card__inner {
|
||||
&:after {
|
||||
content: "";
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.card__expander {
|
||||
max-height: 0;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-expanded {
|
||||
.card__inner {
|
||||
height: auto;
|
||||
@@ -249,7 +234,6 @@ $card-horizontal-gap : $card-gap;
|
||||
|
||||
.card__expander {
|
||||
margin-top: $expanded-margin-top;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@include hover-or-touch {
|
||||
|
||||
Reference in New Issue
Block a user