feat: improve validation message component

This commit is contained in:
tdgao
2026-09-04 13:57:42 -06:00
parent cea2c59573
commit 3427ed20d2
@@ -1,5 +1,7 @@
<template> <template>
<div v-if="validations.length > 0" class="flex w-full flex-col gap-1.5"> <Transition name="validation-message">
<div v-if="validations.length > 0" v-bind="$attrs" class="grid w-full grid-rows-[1fr]">
<div class="flex min-h-0 w-full flex-col gap-1.5 overflow-hidden">
<div <div
v-for="(validation, index) in validations" v-for="(validation, index) in validations"
:key="validation.code ?? validation.message?.id ?? index" :key="validation.code ?? validation.message?.id ?? index"
@@ -18,11 +20,15 @@
? LightBulbIcon ? LightBulbIcon
: TriangleAlertIcon : TriangleAlertIcon
" "
class="mt-0.5" class="mt-0.5 shrink-0"
/> />
{{ validation.message ? formatMessage(validation.message, validation.values) : undefined }} {{
validation.message ? formatMessage(validation.message, validation.values) : undefined
}}
</div> </div>
</div> </div>
</div>
</Transition>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -31,6 +37,8 @@ import type { FieldValidationMessage } from '@modrinth/moderation'
import { injectProjectPageContext, useVIntl } from '@modrinth/ui' import { injectProjectPageContext, useVIntl } from '@modrinth/ui'
import { computed, onScopeDispose, ref, shallowRef, watch } from 'vue' import { computed, onScopeDispose, ref, shallowRef, watch } from 'vue'
defineOptions({ inheritAttrs: false })
type ValidationCheck = Omit<FieldValidationMessage, 'code'> & { code?: string } type ValidationCheck = Omit<FieldValidationMessage, 'code'> & { code?: string }
type ValidationCheckInput = ValidationCheck | ValidationCheck[] | null type ValidationCheckInput = ValidationCheck | ValidationCheck[] | null
@@ -111,3 +119,27 @@ const validations = computed(() => {
: [] : []
}) })
</script> </script>
<style scoped>
.validation-message-enter-active,
.validation-message-leave-active {
transition:
grid-template-rows 150ms ease,
opacity 150ms ease,
transform 150ms ease;
}
.validation-message-enter-from,
.validation-message-leave-to {
grid-template-rows: 0fr;
opacity: 0;
transform: translateY(-0.25rem);
}
@media (prefers-reduced-motion: reduce) {
.validation-message-enter-active,
.validation-message-leave-active {
transition: none;
}
}
</style>