feat(frontend): Add animations for form elements
This commit is contained in:
@@ -49,7 +49,11 @@
|
||||
/* Global focus styles for elements without built-in focus styling.
|
||||
Nuxt UI components (inputs, buttons, selects, etc.) have their own
|
||||
focus ring styling, so we exclude them to avoid double borders. */
|
||||
:focus-visible:not(input):not(textarea):not(select):not(button):not([role="combobox"]):not([role="listbox"]):not([role="option"]):not([role="checkbox"]):not([role="radio"]):not([role="switch"]):not([role="slider"]):not([role="tab"]):not([role="menuitem"]) {
|
||||
:focus-visible:not(input):not(textarea):not(select):not(button):not([role='combobox']):not([role='listbox']):not(
|
||||
[role='option']
|
||||
):not([role='checkbox']):not([role='radio']):not([role='switch']):not([role='slider']):not([role='tab']):not(
|
||||
[role='menuitem']
|
||||
) {
|
||||
outline: 2px solid var(--color-teal-500);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
@@ -95,3 +99,38 @@
|
||||
.dark .nav-separator {
|
||||
background: linear-gradient(90deg, transparent, var(--color-gray-700), transparent);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
FORM ELEMENT VISIBILITY TRANSITIONS
|
||||
============================================ */
|
||||
|
||||
/* Subtle fade + slide animation for form elements appearing/disappearing */
|
||||
.form-element-enter-active {
|
||||
transition:
|
||||
opacity 200ms ease-out,
|
||||
transform 200ms ease-out;
|
||||
}
|
||||
|
||||
.form-element-leave-active {
|
||||
transition:
|
||||
opacity 200ms ease-out,
|
||||
transform 200ms ease-out;
|
||||
/* Take leaving elements out of flow so remaining elements reposition smoothly */
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-element-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
.form-element-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
|
||||
/* Smooth repositioning when elements are added/removed */
|
||||
.form-element-move {
|
||||
transition: transform 200ms ease-out;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<template
|
||||
<TransitionGroup name="form-element" tag="div" class="relative" @before-enter="applyCascadingEntryDelay">
|
||||
<div
|
||||
v-for="(formElementItem, visibleIndex) in visibleFormElements"
|
||||
:key="getElementKey(formElementItem.formElement, formElementItem.indexInSubsection)"
|
||||
:data-index="visibleIndex"
|
||||
>
|
||||
<div class="group flex py-3 lg:py-4">
|
||||
<div class="flex-auto min-w-0">
|
||||
@@ -36,7 +38,9 @@
|
||||
</div>
|
||||
<TheComment
|
||||
v-if="
|
||||
applicationFormId && formElementItem.formElement.id && activeFormElement === formElementItem.formElement.id
|
||||
applicationFormId &&
|
||||
formElementItem.formElement.id &&
|
||||
activeFormElement === formElementItem.formElement.id
|
||||
"
|
||||
:form-element-id="formElementItem.formElement.id"
|
||||
:application-form-id="applicationFormId"
|
||||
@@ -96,7 +100,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<USeparator v-if="visibleIndex < visibleFormElements.length - 1" />
|
||||
</template>
|
||||
</div>
|
||||
</TransitionGroup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -245,4 +250,9 @@ async function toggleComments(formElementId: string) {
|
||||
function handleCloneElement(formElement: FormElementDto, position: number) {
|
||||
emit('clone:element', formElement, position)
|
||||
}
|
||||
|
||||
function applyCascadingEntryDelay(el: Element) {
|
||||
const index = parseInt((el as HTMLElement).dataset.index ?? '0', 10)
|
||||
;(el as HTMLElement).style.transitionDelay = `${index * 30}ms`
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
{{ currentFormElementSection.title }}
|
||||
</h1>
|
||||
|
||||
<TransitionGroup name="form-element" tag="div" class="relative">
|
||||
<UCard
|
||||
v-for="{ subsection, sectionIndex } in visibleSubsections"
|
||||
:key="getSubsectionKey(currentFormElementSection, sectionIndex, subsection)"
|
||||
@@ -75,7 +76,10 @@
|
||||
:all-form-elements="allFormElements"
|
||||
@update:model-value="
|
||||
(elements) =>
|
||||
handleFormElementUpdate(elements, getSubsectionKey(currentFormElementSection, sectionIndex, subsection))
|
||||
handleFormElementUpdate(
|
||||
elements,
|
||||
getSubsectionKey(currentFormElementSection, sectionIndex, subsection)
|
||||
)
|
||||
"
|
||||
@add:input-form="
|
||||
(position) =>
|
||||
@@ -91,6 +95,7 @@
|
||||
"
|
||||
/>
|
||||
</UCard>
|
||||
</TransitionGroup>
|
||||
|
||||
<UCard v-if="visibleSubsections.length === 0" variant="subtle" class="mb-6">
|
||||
<div class="text-center py-8 text-dimmed">
|
||||
|
||||
Reference in New Issue
Block a user