SelectBox: animacja zwijania/rozwijania

This commit is contained in:
2021-07-11 19:10:02 +02:00
parent abba700c18
commit c6f780a2c9
+85 -98
View File
@@ -5,15 +5,15 @@
{{ computedSelectedItem.value }} {{ computedSelectedItem.value }}
</button> </button>
<transition <ul class="options" :ref="(el) => (listRef = el)">
name="expand" <li class="option" v-for="(item, i) in itemList" :key="item.id">
@enter="expandEnter" <transition
@after-enter="expandAfterEnter" name="unfold"
@leave="expandLeave" :style="`
> --delay-in: ${i * 55}ms;
<ul class="options" v-show="listOpen" :ref="(el) => (listRef = el)"> --delay-out: ${(itemList.length - 1 - i) * 55}ms`"
<li class="option" v-for="item in itemList" :key="item.id"> >
<label :for="item.id"> <label :for="item.id" v-if="listOpen">
<input <input
type="button" type="button"
:id="item.id" :id="item.id"
@@ -28,9 +28,9 @@
{{ item.value }} {{ item.value }}
</span> </span>
</label> </label>
</li> </transition>
</ul> </li>
</transition> </ul>
</div> </div>
<div class="arrow"> <div class="arrow">
@@ -83,20 +83,12 @@ export default defineComponent({
); );
}); });
const computedHeight = computed(() =>
listRef.value ? getComputedStyle(listRef.value).height : 0
);
const buttonFocused = computed(() => document.activeElement);
return { return {
computedSelectedItem, computedSelectedItem,
listOpen, listOpen,
selectedItem, selectedItem,
listRef, listRef,
buttonRef, buttonRef,
computedHeight,
buttonFocused,
activeEl, activeEl,
}; };
}, },
@@ -109,40 +101,16 @@ export default defineComponent({
this.$emit("selected", item); this.$emit("selected", item);
}, },
toggleBox() { toggleBox(e: Event) {
this.listOpen = !this.listOpen; this.listOpen = !this.listOpen;
if (!this.listOpen) (e.target as HTMLButtonElement).blur();
}, },
clickedOutside() { clickedOutside() {
this.listOpen = false; this.listOpen = false;
this.buttonRef?.blur(); this.buttonRef?.blur();
}, },
expandEnter(el: HTMLElement) {
el.style.height = "auto";
const currentHeight = getComputedStyle(el).height;
el.style.height = "0";
setTimeout(() => {
el.style.height = currentHeight;
}, 50);
},
expandAfterEnter(el: HTMLElement) {
el.style.height = "auto";
},
expandLeave(el: HTMLElement) {
el.style.height = getComputedStyle(el).height;
getComputedStyle(el);
setTimeout(() => {
el.style.height = "0";
}, 50);
},
}, },
}); });
</script> </script>
@@ -150,11 +118,24 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../../styles/variables.scss"; @import "../../styles/variables.scss";
.expand { .unfold {
&-enter-from,
&-leave-to {
opacity: 0;
transform: translateY(-10px) scale(0.85);
}
&-enter-active, &-enter-active,
&-leave-active { &-leave-active {
transition: height 150ms ease-out; transition: all 110ms ease-out;
overflow: hidden; }
&-enter-active {
transition-delay: var(--delay-in);
}
&-leave-active {
transition-delay: var(--delay-out);
} }
} }
@@ -177,31 +158,6 @@ export default defineComponent({
pointer-events: none; pointer-events: none;
} }
.select-box_content {
position: relative;
margin: 0 auto;
height: 100%;
min-width: 10em;
text-align: center;
}
.options {
position: absolute;
top: 100%;
left: 0;
height: auto;
z-index: 10;
width: 100%;
margin-top: 0.25em;
}
button.selected { button.selected {
background: #333; background: #333;
color: white; color: white;
@@ -224,37 +180,68 @@ button.selected {
} }
} }
input { .select-box_content {
position: absolute; position: relative;
top: 0; margin: 0 auto;
left: 0;
-webkit-appearance: none; height: 100%;
-moz-appearance: none;
appearance: none;
border: none;
&:focus + span { min-width: 10em;
color: $accentCol;
font-weight: bold; text-align: center;
}
} }
label { ul.options {
position: relative; position: absolute;
top: 100%;
left: 0;
display: inline-block; height: auto;
background-color: hsla(0, 0%, 0%, 0.85);
&:hover, z-index: 10;
&:focus {
background-color: hsla(0, 0%, 20%, 0.85);
}
padding: 0.75em 0;
width: 100%; width: 100%;
cursor: pointer; margin-top: 0.25em;
}
li.option {
input {
position: absolute;
top: 0;
left: 0;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: none;
&:focus + span {
color: $accentCol;
font-weight: bold;
}
}
&:last-child label {
border-radius: 0 0 1em 1em;
}
label {
position: relative;
display: inline-block;
background-color: hsla(0, 0%, 15%, 0.95);
&:hover,
&:focus {
background-color: hsla(0, 0%, 20%, 0.95);
}
padding: 0.75em 0;
width: 100%;
cursor: pointer;
}
} }
</style> </style>