Skip to content

Commit

Permalink
[#2871] fallback component integration for va-image (#2874)
Browse files Browse the repository at this point in the history
  • Loading branch information
aluarius authored Jan 30, 2023
1 parent 0aa273c commit 9dc0c8e
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/docs/src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2653,7 +2653,7 @@
},
"slots": {
"title": "Status slots",
"text": "We're providing 3 status slots: `error` (visible when `src` path is incorrect), `loading` (visible when image is loading) and `placeholder` (works as both previous)."
"text": "We're providing 3 status slots: `error` (visible when `src` path is incorrect), `loading` (visible when image is loading) and `placeholder` (works as both previous). As an alternative for error handling, we provide the `fallback-icon`, `fallback-text`, `fallback-image` and `fallback-renderer` props, that will be called if error slot wasn't passed. Also you're able to set global fallback settings via [components config](/getting-started/configuration-guide#components-config)."
},
"srcSet": {
"title": "Srcset",
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/locales/ru/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -2527,7 +2527,7 @@
},
"slots": {
"title": "Слоты состояний",
"text": "Мы предоставляем 3 слота состояния: `error` (содержимое отображается когда `src` некорректен), `loading` (содержимое отображается когда изображение грузится) and `placeholder` (универсальное решение, заменяющее 2 предыдущих)."
"text": "Мы предоставляем 3 слота состояния: `error` (содержимое отображается когда `src` некорректен), `loading` (содержимое отображается когда изображение грузится) and `placeholder` (универсальное решение, заменяющее 2 предыдущих). Также, в качестве альтернативного способа обработки ошибок, вы можете передавать свойства `fallback-icon`, `fallback-text`, `fallback-image` и `fallback-renderer`, которые будут отрабатывать, если `error` слот не был передан. Кроме того, вы можете установить глобальный настройки фолбэка с помощью [components config](/getting-started/configuration-guide#components-config)."
},
"srcSet": {
"title": "Srcset",
Expand Down
40 changes: 24 additions & 16 deletions packages/docs/src/page-configs/ui-elements/image/examples/Slots.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,30 @@
Wrong path
</va-button>
</div>
<va-image
class="flex flex-col md6 lg4"
:src="slotImagePath"
@loaded="consoleLog"
@error="consoleLog"
>
<template #loader>
<va-progress-circle indeterminate />
</template>

<template #error>
<div class="p-8 flex items-center justify-center bg-red-300 rounded-3xl">
<va-icon name="close" color="danger" :size="32" />
</div>
</template>
</va-image>
<div class="row space-x-4">
<va-image
class="flex flex-col md6 lg4"
:src="slotImagePath"
@loaded="consoleLog"
@error="consoleLog"
>
<template #loader>
<va-progress-circle indeterminate />
</template>

<template #error>
<div class="p-8 flex items-center justify-center bg-red-300 rounded-3xl">
<va-icon name="close" color="danger" :size="32" />
</div>
</template>
</va-image>

<va-image
class="flex flex-col md6 lg4"
:src="slotImagePath"
fallback-text="Fallback will work if error slot wasn't passed"
/>
</div>
</template>

<script setup>
Expand Down
4 changes: 0 additions & 4 deletions packages/ui/src/components/va-fallback/VaFallback.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,15 @@ export default defineComponent({
props: {
fallbackSrc: {
type: String,
default: '',
},
fallbackText: {
type: String,
default: '',
},
fallbackIcon: {
type: String,
default: '',
},
fallbackRender: {
type: Function as PropType<() => any | undefined>,
default: undefined,
},
},
Expand Down
8 changes: 7 additions & 1 deletion packages/ui/src/components/va-image/VaImage.demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,19 @@
</va-image>

<va-image
class="image"
class="image mb-2"
:src="slotImagePath"
>
<template #placeholder>
Placeholder (both error and loading states)
</template>
</va-image>

<va-image
class="image"
:src="slotImagePath"
fallback-text="Fallback text"
/>
</VbCard>

<VbCard title="Default slot">
Expand Down
31 changes: 25 additions & 6 deletions packages/ui/src/components/va-image/VaImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
</div>

<div
v-if="isError && $slots.error"
v-if="isError && ($slots.error || isAnyFallbackPassed)"
class="va-image__error"
>
<slot name="error" />
<slot name="error">
<va-fallback v-bind="fallbackProps" @fallback="$emit('fallback')" />
</slot>
</div>

<div
Expand Down Expand Up @@ -69,25 +71,32 @@ import {
} from 'vue'
import { VaAspectRatio } from '../va-aspect-ratio'
import { VaFallback } from '../va-fallback'
import { useNativeImgAttributes, useNativeImgAttributesProps } from './hooks/useNativeImgAttributes'
import {
useComponentPresetProp,
useIsMounted,
useDeprecated,
useIntersectionObserver,
useGlobalConfig,
} from '../../composables'
import { extractComponentProps, filterComponentProps } from '../../utils/component-options'
const VaFallbackProps = extractComponentProps(VaFallback)
export default defineComponent({
name: 'VaImage',
components: { VaAspectRatio },
components: { VaAspectRatio, VaFallback },
emits: ['loaded', 'error'],
emits: ['loaded', 'error', 'fallback'],
props: {
...useComponentPresetProp,
...useNativeImgAttributesProps,
...VaFallbackProps,
ratio: {
type: [Number, String] as PropType<number | 'auto'>,
default: 'auto',
Expand Down Expand Up @@ -201,8 +210,10 @@ export default defineComponent({
onBeforeUnmount(() => clearTimeout(timer))
watch(() => props.src, init)
const isPlaceholderShown = computed(() =>
((isLoading.value && !slots?.loader?.()) || (isError.value && !slots?.error?.())) && (slots?.placeholder?.() || props.placeholderSrc))
const isPlaceholderPassed = computed(() => slots?.placeholder?.() || props.placeholderSrc)
const isLoaderShown = computed(() => isLoading.value && !slots?.loader?.())
const isErrorShown = computed(() => isError.value && (!slots?.error?.() && !isAnyFallbackPassed.value))
const isPlaceholderShown = computed(() => (isLoaderShown.value || isErrorShown.value) && isPlaceholderPassed.value)
const isSuccessfullyLoaded = computed(() => !(isLoading.value || isError.value))
Expand All @@ -214,6 +225,11 @@ export default defineComponent({
ratio: props.ratio,
}))
const fallbackProps = filterComponentProps(VaFallbackProps)
const checkObjectNonEmptyValues = (obj: Record<string, any> | undefined) => !!Object.values(obj || {}).filter((prop) => prop).length
const hasFallbackGlobalConfig = computed(() => checkObjectNonEmptyValues(useGlobalConfig()?.globalConfig?.value?.components?.VaFallback))
const isAnyFallbackPassed = computed(() => checkObjectNonEmptyValues(fallbackProps.value) || hasFallbackGlobalConfig.value)
// TODO: refactor (just v-bind fit prop to CSS) in 1.7.0
const fitComputed = computed(() => {
if (props.contain) { return 'contain' }
Expand All @@ -236,6 +252,9 @@ export default defineComponent({
isSuccessfullyLoaded,
imgAttributesComputed,
aspectRationAttributesComputed,
isAnyFallbackPassed,
fallbackProps,
}
},
})
Expand Down

0 comments on commit 9dc0c8e

Please sign in to comment.