Browse Source

Fix toggle switch CSS and table flickering

- Use unique class .slider-large instead of .toggle-slider to avoid
  Vue scoped CSS conflicts
- Show loading/error only when devices array is empty
- Don't hide table during background refresh

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
root 2 weeks ago
parent
commit
9a21731d09
1 changed files with 10 additions and 10 deletions
  1. 10 10
      frontend/src/views/superadmin/DevicesView.vue

+ 10 - 10
frontend/src/views/superadmin/DevicesView.vue

@@ -31,7 +31,7 @@
               @change="toggleAutoRegistration"
               @change="toggleAutoRegistration"
               :disabled="togglingRegistration"
               :disabled="togglingRegistration"
             />
             />
-            <span class="toggle-slider"></span>
+            <span class="slider-large"></span>
             <span v-if="togglingRegistration" class="spinner">⏳</span>
             <span v-if="togglingRegistration" class="spinner">⏳</span>
           </label>
           </label>
         </div>
         </div>
@@ -62,9 +62,9 @@
         </button>
         </button>
       </div>
       </div>
 
 
-      <div v-if="loading" class="loading">{{ $t('common.loading') }}</div>
+      <div v-if="loading && devices.length === 0" class="loading">{{ $t('common.loading') }}</div>
 
 
-      <div v-else-if="error" class="error">{{ error }}</div>
+      <div v-else-if="error && devices.length === 0" class="error">{{ error }}</div>
 
 
       <table v-else-if="devices.length > 0" class="data-table">
       <table v-else-if="devices.length > 0" class="data-table">
         <thead>
         <thead>
@@ -141,7 +141,7 @@
         </tbody>
         </tbody>
       </table>
       </table>
 
 
-      <div v-else class="empty">No devices yet</div>
+      <div v-else-if="!loading" class="empty">No devices yet</div>
     </div>
     </div>
 
 
     <!-- Edit Modal -->
     <!-- Edit Modal -->
@@ -1158,7 +1158,7 @@ onBeforeUnmount(() => {
   height: 0;
   height: 0;
   position: absolute;
   position: absolute;
 }
 }
-.toggle-switch-large .toggle-slider {
+.slider-large {
   position: absolute;
   position: absolute;
   cursor: pointer;
   cursor: pointer;
   top: 0;
   top: 0;
@@ -1170,7 +1170,7 @@ onBeforeUnmount(() => {
   border-radius: 40px;
   border-radius: 40px;
   box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
   box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
 }
 }
-.toggle-switch-large .toggle-slider:before {
+.slider-large:before {
   position: absolute;
   position: absolute;
   content: '';
   content: '';
   height: 32px;
   height: 32px;
@@ -1182,16 +1182,16 @@ onBeforeUnmount(() => {
   border-radius: 50%;
   border-radius: 50%;
   box-shadow: 0 2px 8px rgba(0,0,0,0.2);
   box-shadow: 0 2px 8px rgba(0,0,0,0.2);
 }
 }
-.toggle-switch-large input:checked + .toggle-slider {
+.toggle-switch-large input:checked + .slider-large {
   background-color: #48bb78;
   background-color: #48bb78;
 }
 }
-.toggle-switch-large input:checked + .toggle-slider:before {
+.toggle-switch-large input:checked + .slider-large:before {
   transform: translateX(32px);
   transform: translateX(32px);
 }
 }
-.toggle-switch-large input:focus + .toggle-slider {
+.toggle-switch-large input:focus + .slider-large {
   box-shadow: inset 0 2px 4px rgba(0,0,0,0.1), 0 0 0 3px rgba(72, 187, 120, 0.3);
   box-shadow: inset 0 2px 4px rgba(0,0,0,0.1), 0 0 0 3px rgba(72, 187, 120, 0.3);
 }
 }
-.toggle-switch-large input:disabled + .toggle-slider {
+.toggle-switch-large input:disabled + .slider-large {
   opacity: 0.5;
   opacity: 0.5;
   cursor: not-allowed;
   cursor: not-allowed;
 }
 }