Skip to content
Snippets Groups Projects
Commit 5b299ce5 authored by Дмитрий Малюгин's avatar Дмитрий Малюгин :clock4:
Browse files

fix: animation in 'Toast'

parent 27536701
No related branches found
No related tags found
1 merge request!6Finish "UI-library v1.0.0"
...@@ -197,10 +197,10 @@ const openDrawer = () => (visibleDrawer.value = true); ...@@ -197,10 +197,10 @@ const openDrawer = () => (visibleDrawer.value = true);
" "
/> />
<Button label="Open toast" @click="toast2 = true" /> <Button label="Open toast" @click="toast2 = true" />
<Toast v-model="toast" static type="success" position="top" width="500px" /> <Toast v-model="toast" static duration="60" type="success" position="top" width="500px" />
<Toast v-model="toast4" type="info" position="top" width="500px" /> <Toast v-model="toast4" duration="60" type="info" position="top" width="500px" />
<Toast v-model="toast3" type="warn" position="top" width="500px" /> <Toast v-model="toast3" duration="60" type="warn" position="top" width="500px" />
<Toast v-model="toast2" type="error" position="top" width="500px" /> <Toast v-model="toast2" duration="60" type="error" position="top" width="500px" />
<Rating theme="red"> <Rating theme="red">
<template #offIcon> <template #offIcon>
<CrossIcon color="red" /> <CrossIcon color="red" />
......
...@@ -38,13 +38,15 @@ const typeToIcon: Record<TToastType, string> = { ...@@ -38,13 +38,15 @@ const typeToIcon: Record<TToastType, string> = {
const active = defineModel() as Ref<boolean>; const active = defineModel() as Ref<boolean>;
let toastsContainer: HTMLElement = document.querySelector(`.toasts-container.${props.position}`)!; let toastsContainer: HTMLElement = document.querySelector(`.toasts-container.${props.position}`) as HTMLElement;
const toast = ref<HTMLElement>() as Ref<HTMLElement>; const toast = ref<HTMLElement>() as Ref<HTMLElement>;
watch([toast], () => { watch([toast, () => props.static], () => {
if (toast.value) { if (toast.value && !props.static) {
toastsContainer?.appendChild(toast.value); toastsContainer?.appendChild(toast.value);
} }
if (props.static) {
}
}); });
const themeColor = computed<TThemeColor>(() => props.theme ?? typeToTheme[props.type]); const themeColor = computed<TThemeColor>(() => props.theme ?? typeToTheme[props.type]);
...@@ -64,7 +66,9 @@ const backgroundColor = computed(() => ...@@ -64,7 +66,9 @@ const backgroundColor = computed(() =>
const borderColor = computed(() => convertThemeToColor(themeColor.value, '500')); const borderColor = computed(() => convertThemeToColor(themeColor.value, '500'));
const fontSize = computed(() => getValueFromSize(props.size, ['12px', '16px', '20px', '24px'])); const fontSize = computed(() => getValueFromSize(props.size, ['12px', '16px', '20px', '24px']));
const padding = computed( const padding = computed(
() => getValueFromSize(props.size, ['7px 10px', '10px 15px', '14px 20px', '20px 30px']) as string, () =>
(props.static || active.value) &&
(getValueFromSize(props.size, ['7px 10px', '10px 15px', '14px 20px', '20px 30px']) as string),
); );
const gap = computed(() => const gap = computed(() =>
props.size === 'normal' ? '10px' : props.size === 'large' || props.size === 'huge' ? '15px' : '5px', props.size === 'normal' ? '10px' : props.size === 'large' || props.size === 'huge' ? '15px' : '5px',
...@@ -91,24 +95,26 @@ const styles = computed(() => { ...@@ -91,24 +95,26 @@ const styles = computed(() => {
if (positionParts.value.length === 1) { if (positionParts.value.length === 1) {
const position = positionParts.value[0]; const position = positionParts.value[0];
// if (position === 'left' || position === 'right') // if (position === 'left' || position === 'right')
// return `${position}: -100%; top: 50%; transform: translateY(-50%);`; // return `${position}: -100%; top: 50%; transform: translateY(-50%)`;
return `${position}: -100%; left: 50%; transform: translateX(-50%);`; return `${position}: -100%; left: 50%; transform: translateX(-50%)`;
} }
return `${positionParts.value[0]}: -100%; ${positionParts.value[1]}: 20px;`; return `${positionParts.value[0]}: -100%; ${positionParts.value[1]}: 20px`;
}); });
const initContainer = () => { const initContainer = () => {
if (!toastsContainer) { if (!toastsContainer && !props.static) {
toastsContainer = document.createElement('div'); toastsContainer = document.createElement('div');
toastsContainer.classList.add('toasts-container'); toastsContainer.classList.add('toasts-container');
toastsContainer.classList.add(`${props.position}`); toastsContainer.classList.add(`${props.position}`);
toastsContainer.style = ` toastsContainer.style.position = 'fixed';
position: fixed; toastsContainer.style.zIndex = '9999';
display: flex; toastsContainer.style.display = 'flex';
flex-direction: ${positionParts.value.find((i) => i === 'bottom') ? 'column-reverse' : 'column'}; toastsContainer.style.flexDirection = positionParts.value.find((i) => i === 'bottom') ? 'column-reverse' : 'column';
gap: 20px; toastsContainer.style.transition = 'all 0.5s ease-in-out';
transition: all 0.4s ease-in-out; for (const item of styles.value.split('; ')) {
${styles.value} const splatItem = item.split(':');
`; if (splatItem[0] === '') break;
toastsContainer.style[splatItem[0]] = splatItem[1];
}
document.body.appendChild(toastsContainer); document.body.appendChild(toastsContainer);
} }
}; };
...@@ -125,33 +131,18 @@ const closeToast = () => (active.value = false); ...@@ -125,33 +131,18 @@ const closeToast = () => (active.value = false);
let timeout: number; let timeout: number;
if (props.duration) { watch(active, () => {
watch(active, () => { console.log('props.duration,props.static:', props.duration, props.static);
if (active.value) { if (props.static) return;
toast.value.classList.add('active'); if (active.value) {
const activeToasts = document.querySelectorAll(`.toast-container.${props.position}.active`); toast.value.classList.add('active');
let activeToastsHeight = 0; toastsContainer.style[positionParts.value[0] as 'top' | 'bottom'] = '20px';
for (const toast of activeToasts) { timeout = setTimeout(() => (active.value = false), (props.duration as number) * 1000);
activeToastsHeight += toast.offsetHeight; } else if (props.duration) {
} toast.value.classList.remove('active');
toast.value.style.order = '9999'; clearTimeout(timeout);
const offset = activeToastsHeight + 20 * activeToasts.length; }
toastsContainer.style[positionParts.value[0] as 'top' | 'bottom'] = offset - toastsContainer?.clientHeight + 'px'; });
timeout = setTimeout(() => (active.value = false), (props.duration as number) * 1000);
} else {
toast.value.classList.remove('active');
const activeToasts = document.querySelectorAll(`.toast-container.${props.position}.active`);
let activeToastsHeight = 0;
for (const toast of activeToasts) {
activeToastsHeight += toast.offsetHeight;
}
toast.value.style.order = '1';
const offset = activeToastsHeight + 20 * activeToasts.length;
toastsContainer.style[positionParts.value[0] as 'top' | 'bottom'] = offset - toastsContainer?.clientHeight + 'px';
clearTimeout(timeout);
}
});
}
</script> </script>
<template> <template>
...@@ -165,7 +156,7 @@ if (props.duration) { ...@@ -165,7 +156,7 @@ if (props.duration) {
oneAxis: positionParts.length === 1, oneAxis: positionParts.length === 1,
}, },
]" ]"
:style="`position: relative; :style="`position: relative; margin-bottom: ${active ? '20px' : '0'};
${styles}`" ${styles}`"
> >
<h3 class="toast-header" :style="`font-size: calc(${fontSize} + 4px)`"> <h3 class="toast-header" :style="`font-size: calc(${fontSize} + 4px)`">
...@@ -176,7 +167,7 @@ if (props.duration) { ...@@ -176,7 +167,7 @@ if (props.duration) {
<CrossIcon <CrossIcon
@click="closeToast" @click="closeToast"
class="toast-close_button" class="toast-close_button"
:style="`top: ${padding.split(' ')[0]}; right: ${padding.split(' ')[1]}`" :style="`top: ${padding && padding.split(' ')[0]}; right: ${padding && padding.split(' ')[1]}`"
:color="color" :color="color"
:size="iconSize" :size="iconSize"
/> />
...@@ -189,7 +180,11 @@ if (props.duration) { ...@@ -189,7 +180,11 @@ if (props.duration) {
padding: v-bind(padding); padding: v-bind(padding);
border: 1px solid v-bind(borderColor); border: 1px solid v-bind(borderColor);
border-radius: 7px; border-radius: 7px;
transition: all 0.5s ease-in-out; transition:
all 0.5s ease-in-out,
max-height 0.01s ease-in-out,
padding 0.2s ease-in-out,
margin 0.2s ease-in-out;
width: v-bind(width); width: v-bind(width);
::before { ::before {
content: ''; content: '';
...@@ -225,27 +220,35 @@ if (props.duration) { ...@@ -225,27 +220,35 @@ if (props.duration) {
display: block; display: block;
} }
.top { .top {
transform: translateY(-1000px); transform: translateY(-500px);
max-height: 0;
} }
.bottom { .bottom {
transform: translateY(1000px); transform: translateY(500px);
max-height: 0;
} }
.active.top { .active.top {
transform: translateY(0); transform: translateY(0);
max-height: 1000px;
} }
.active.bottom { .active.bottom {
transform: translateY(0); transform: translateY(0);
max-height: 1000px;
} }
.oneAxis.top { .oneAxis.top {
transform: translate(-50%, -1000px) !important; transform: translate(-50%, -500px) !important;
max-height: 0;
} }
.oneAxis.bottom { .oneAxis.bottom {
transform: translate(-50%, 1000px) !important; transform: translate(-50%, 500px) !important;
max-height: 0;
} }
.oneAxis.active.top { .oneAxis.active.top {
transform: translate(-50%, 0) !important; transform: translate(-50%, 0) !important;
max-height: 1000px;
} }
.oneAxis.active.bottom { .oneAxis.active.bottom {
transform: translate(-50%, 0) !important; transform: translate(-50%, 0) !important;
max-height: 1000px;
} }
</style> </style>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment