diff --git a/ui/src/routes/devices.$id.settings.tsx b/ui/src/routes/devices.$id.settings.tsx
index b68e7df..d26c488 100644
--- a/ui/src/routes/devices.$id.settings.tsx
+++ b/ui/src/routes/devices.$id.settings.tsx
@@ -11,16 +11,50 @@ import {
LuPalette,
} from "react-icons/lu";
import { LinkButton } from "../components/Button";
-import React, { useEffect } from "react";
+import React, { useEffect, useRef, useState } from "react";
import { cx } from "../cva.config";
import { useUiStore } from "../hooks/stores";
import useKeyboard from "../hooks/useKeyboard";
+import { useResizeObserver } from "../hooks/useResizeObserver";
/* TODO: Migrate to using URLs instead of the global state. To simplify the refactoring, we'll keep the global state for now. */
export default function SettingsRoute() {
const location = useLocation();
const setDisableVideoFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap);
const { sendKeyboardEvent } = useKeyboard();
+ const scrollContainerRef = useRef
(null);
+ const [showLeftGradient, setShowLeftGradient] = useState(false);
+ const [showRightGradient, setShowRightGradient] = useState(false);
+ const { width } = useResizeObserver({ ref: scrollContainerRef });
+
+ // Handle scroll position to show/hide gradients
+ const handleScroll = () => {
+ if (scrollContainerRef.current) {
+ const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current;
+ // Show left gradient only if scrolled to the right
+ setShowLeftGradient(scrollLeft > 0);
+ // Show right gradient only if there's more content to scroll to the right
+ setShowRightGradient(scrollLeft < scrollWidth - clientWidth - 1); // -1 for rounding errors
+ }
+ };
+
+ useEffect(() => {
+ // Check initial scroll position
+ handleScroll();
+
+ // Add scroll event listener to the container
+ const scrollContainer = scrollContainerRef.current;
+ if (scrollContainer) {
+ scrollContainer.addEventListener("scroll", handleScroll);
+ }
+
+ return () => {
+ // Clean up event listener
+ if (scrollContainer) {
+ scrollContainer.removeEventListener("scroll", handleScroll);
+ }
+ };
+ }, [width]);
useEffect(() => {
// disable focus trap
@@ -42,9 +76,9 @@ export default function SettingsRoute() {
return (
-
+
-
+
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
General
-
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Mouse
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Video
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Hardware
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Security
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Appearance
-
-
-
-
-
(isActive ? "active" : "")}
- >
-
-
-
Advanced
-
-
+
+ {/* Gradient overlay for left side - only visible on mobile when scrolled */}
+
+ {/* Gradient overlay for right side - only visible on mobile when there's more content */}
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
General
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Mouse
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Video
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Hardware
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Security
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Appearance
+
+
+
+
+
(isActive ? "active" : "")}
+ >
+
+
+
Advanced
+
+
+