feat: Add configurable transition speed for route animations

This commit introduces a new feature allowing you to control the speed
of route transitions.

Changes include:
- Added `transitionSpeed` state (defaulting to 1 for normal) and a
  `setTransitionSpeed` action to `ui/src/stores/useUi.js`. The speed
  is a multiplier for the base transition duration.
- `transitionSpeed` is now persisted to local storage.
- Modified `ui/src/App.vue` to dynamically calculate and apply the
  transition duration using a CSS variable (`--current-transition-duration`)
  based on the `transitionSpeed` from the store. The base duration for
  normal speed is 0.3s.
- Added a new "Animation Speed" setting in `ui/src/views/SettingsView.vue`
  with options (Slow, Normal, Fast) using radio buttons. This control
  updates the `transitionSpeed` in the UI store.

This allows you to customize the feel of the application's navigation
transitions to your preference.
This commit is contained in:
google-labs-jules[bot]
2025-05-31 08:31:45 +00:00
parent 5edc9da769
commit cd2f62c89d
3 changed files with 47 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { watchEffect } from 'vue' import { watchEffect, computed } from 'vue' // Added computed
import TopBar from '@/components/ui/TopBar.vue' import TopBar from '@/components/ui/TopBar.vue'
import NavBar from '@/components/ui/NavBar.vue' import NavBar from '@/components/ui/NavBar.vue'
import { useUi } from '@/stores/useUi' import { useUi } from '@/stores/useUi'
@@ -46,6 +46,15 @@ watchEffect(() => {
root.classList.add('animations-disabled') root.classList.add('animations-disabled')
} }
}) })
const transitionDurationStyle = computed(() => {
// Assuming base duration of 0.3s for normal speed (transitionSpeed = 1)
const baseDuration = 0.3
const effectiveDuration = baseDuration * ui.transitionSpeed
return {
'--current-transition-duration': `${effectiveDuration}s`
}
})
</script> </script>
<template> <template>
@@ -59,7 +68,7 @@ watchEffect(() => {
// The global style.css will handle base background and text color via body styling // The global style.css will handle base background and text color via body styling
// but we can keep specific overrides here if needed or theme classes. // but we can keep specific overrides here if needed or theme classes.
// ui.theme === 'dark' ? 'bg-gray-800 text-gray-100' : 'bg-gray-100 text-gray-900' // ui.theme === 'dark' ? 'bg-gray-800 text-gray-100' : 'bg-gray-100 text-gray-900'
]"> ]" :style="transitionDurationStyle"> {/* Apply style here */}
<!-- NavBar fija --> <!-- NavBar fija -->
<NavBar /> <NavBar />
@@ -80,7 +89,7 @@ watchEffect(() => {
.slide-fade-enter-active, .slide-fade-enter-active,
.slide-fade-leave-active { .slide-fade-leave-active {
transition: all 0.3s ease-out; /* Increased duration for a smoother slide */ transition: all var(--current-transition-duration) ease-out; /* Use the CSS variable */
} }
.slide-fade-enter-from { .slide-fade-enter-from {

View File

@@ -30,6 +30,7 @@ const appearanceSettingKeys = [
'defaultViewPlanillas', 'defaultViewPlanillas',
'defaultViewAsistencias', 'defaultViewAsistencias',
'defaultViewConfiguracion', 'defaultViewConfiguracion',
'transitionSpeed',
] ]
const loadSettingsFromLocalStorage = () => { const loadSettingsFromLocalStorage = () => {
@@ -104,6 +105,7 @@ export const useUi = defineStore('ui', {
'defaultViewPlanillas': 'table', 'defaultViewPlanillas': 'table',
'defaultViewAsistencias': 'table', 'defaultViewAsistencias': 'table',
'defaultViewConfiguracion': 'table', 'defaultViewConfiguracion': 'table',
transitionSpeed: 1, // Default to normal speed
} }
const loadedSettings = loadSettingsFromLocalStorage() const loadedSettings = loadSettingsFromLocalStorage()
@@ -237,7 +239,13 @@ export const useUi = defineStore('ui', {
setDefaultViewConfiguracion(view) { setDefaultViewConfiguracion(view) {
this.defaultViewConfiguracion = view this.defaultViewConfiguracion = view
_saveAppearanceState(this) _saveAppearanceState(this)
} },
// Action for transition speed
setTransitionSpeed(newSpeed) {
this.transitionSpeed = Number(newSpeed) // Ensure it's a number
_saveAppearanceState(this)
},
}, },
}) })

View File

@@ -26,6 +26,26 @@
<input type="checkbox" id="desktopNavbarPersistent" v-model="ui.desktopNavbarPersistent" @change="ui.setDesktopNavbarPersistent($event.target.checked)" <input type="checkbox" id="desktopNavbarPersistent" v-model="ui.desktopNavbarPersistent" @change="ui.setDesktopNavbarPersistent($event.target.checked)"
class="custom-checkbox relative w-10 h-5 appearance-none bg-gray-300 dark:bg-gray-600 rounded-full cursor-pointer transition-colors duration-300 ease-in-out checked:bg-[var(--primary-color)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--primary-color)] focus:ring-offset-[var(--background-color)]"> class="custom-checkbox relative w-10 h-5 appearance-none bg-gray-300 dark:bg-gray-600 rounded-full cursor-pointer transition-colors duration-300 ease-in-out checked:bg-[var(--primary-color)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--primary-color)] focus:ring-offset-[var(--background-color)]">
</div> </div>
<!-- Animation Speed Setting -->
<div class="setting-item mt-6 md:col-span-2"> <!-- md:col-span-2 to make it take full width on medium screens if the grid has 2 columns -->
<label class="block text-sm font-medium mb-1 text-[var(--text-color)]">Animation Speed</label>
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
Adjust the speed of screen transitions (applied if animations are enabled).
</p>
<div class="flex flex-col space-y-1 sm:flex-row sm:space-y-0 sm:space-x-4">
<label v-for="option in speedOptions" :key="option.value"
class="flex items-center p-2 rounded-md hover:bg-gray-200/50 dark:hover:bg-gray-700/50 cursor-pointer transition-colors duration-150 ease-in-out border border-gray-300 dark:border-gray-600 hover:border-[var(--primary-color)]">
<input type="radio"
name="transitionSpeed"
:value="option.value"
:checked="ui.transitionSpeed === option.value"
@change="ui.setTransitionSpeed(option.value)"
class="form-radio h-4 w-4 text-[var(--primary-color)] focus:ring-1 focus:ring-[var(--primary-color)] border-gray-300 dark:border-gray-500 bg-white dark:bg-gray-800 focus:ring-offset-white dark:focus:ring-offset-gray-900">
<span class="ml-2 text-sm text-[var(--text-color)]">{{ option.label }} <span class="text-xs text-gray-500 dark:text-gray-400">({{ option.value }}x)</span></span>
</label>
</div>
</div>
</div> </div>
</section> </section>
@@ -211,6 +231,12 @@ onMounted(() => {
isMounted.value = true isMounted.value = true
}, 50) }, 50)
}) })
const speedOptions = [
{ label: 'Slow', value: 2 },
{ label: 'Normal', value: 1 },
{ label: 'Fast', value: 0.5 },
]
</script> </script>
<style scoped> <style scoped>