Skip to content

Commit 9438ab7

Browse files
authored
Fix the lazy loading for the settings page. (#837)
Move SettingsItem into it's own page Packages upgraded @headlessui/react 2.2.8 -> 2.2.9 framer-motion 12.23.18 -> 12/23/22 react-router 7.9.1 -> 7.9.3 @tailwindcss/typography 0.6.18 -> 0.5.19 @types/react 19.1.13 -> 19.1.14 eslint-plugin-react-refresh 0.4.21 -> 0.4.22
1 parent 12d31a3 commit 9438ab7

15 files changed

+245
-249
lines changed

ui/package-lock.json

Lines changed: 180 additions & 180 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "kvm-ui",
33
"private": true,
4-
"version": "2025.09.23.0000",
4+
"version": "2025.09.26.01300",
55
"type": "module",
66
"engines": {
77
"node": "^22.15.0"
@@ -19,7 +19,7 @@
1919
"preview": "vite preview"
2020
},
2121
"dependencies": {
22-
"@headlessui/react": "^2.2.8",
22+
"@headlessui/react": "^2.2.9",
2323
"@headlessui/tailwindcss": "^0.2.2",
2424
"@heroicons/react": "^2.2.0",
2525
"@vitejs/plugin-basic-ssl": "^2.1.0",
@@ -33,15 +33,15 @@
3333
"dayjs": "^1.11.18",
3434
"eslint-import-resolver-alias": "^1.1.2",
3535
"focus-trap-react": "^11.0.4",
36-
"framer-motion": "^12.23.18",
36+
"framer-motion": "^12.23.22",
3737
"lodash.throttle": "^4.1.1",
3838
"mini-svg-data-uri": "^1.4.4",
3939
"react": "^19.1.1",
4040
"react-animate-height": "^3.2.3",
4141
"react-dom": "^19.1.1",
4242
"react-hot-toast": "^2.6.0",
4343
"react-icons": "^5.5.0",
44-
"react-router": "^7.9.1",
44+
"react-router": "^7.9.3",
4545
"react-simple-keyboard": "^3.8.122",
4646
"react-use-websocket": "^4.13.0",
4747
"react-xtermjs": "^1.0.10",
@@ -57,9 +57,9 @@
5757
"@eslint/js": "^9.36.0",
5858
"@tailwindcss/forms": "^0.5.10",
5959
"@tailwindcss/postcss": "^4.1.13",
60-
"@tailwindcss/typography": "^0.5.18",
60+
"@tailwindcss/typography": "^0.5.19",
6161
"@tailwindcss/vite": "^4.1.13",
62-
"@types/react": "^19.1.13",
62+
"@types/react": "^19.1.14",
6363
"@types/react-dom": "^19.1.9",
6464
"@types/semver": "^7.7.1",
6565
"@types/validator": "^13.15.3",
@@ -72,7 +72,7 @@
7272
"eslint-plugin-import": "^2.32.0",
7373
"eslint-plugin-react": "^7.37.5",
7474
"eslint-plugin-react-hooks": "^5.2.0",
75-
"eslint-plugin-react-refresh": "^0.4.21",
75+
"eslint-plugin-react-refresh": "^0.4.22",
7676
"globals": "^16.4.0",
7777
"postcss": "^8.5.6",
7878
"prettier": "^3.6.2",

ui/src/components/SettingsItem.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { cx } from "@/cva.config";
2+
import LoadingSpinner from "@components/LoadingSpinner";
3+
4+
interface SettingsItemProps {
5+
readonly title: string;
6+
readonly description: string | React.ReactNode;
7+
readonly badge?: string;
8+
readonly className?: string;
9+
readonly loading?: boolean;
10+
readonly children?: React.ReactNode;
11+
}
12+
13+
export function SettingsItem(props: SettingsItemProps) {
14+
const { title, description, badge, children, className, loading } = props;
15+
16+
return (
17+
<label
18+
className={cx(
19+
"flex select-none items-center justify-between gap-x-8 rounded",
20+
className,
21+
)}
22+
>
23+
<div className="space-y-0.5">
24+
<div className="flex items-center gap-x-2">
25+
<div className="flex items-center text-base font-semibold text-black dark:text-white">
26+
{title}
27+
{badge && (
28+
<span className="ml-2 rounded-full bg-red-500 px-2 py-1 text-[10px] font-medium leading-none text-white dark:border dark:border-red-700 dark:bg-red-800 dark:text-red-50">
29+
{badge}
30+
</span>
31+
)}
32+
</div>
33+
{loading && <LoadingSpinner className="h-4 w-4 text-blue-500" />}
34+
</div>
35+
<div className="text-sm text-slate-700 dark:text-slate-300">{description}</div>
36+
</div>
37+
{children ? <div>{children}</div> : null}
38+
</label>
39+
);
40+
}

ui/src/components/UsbDeviceSetting.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useCallback , useEffect, useState } from "react";
22

3+
import { SettingsItem } from "@components/SettingsItem";
4+
35
import { JsonRpcResponse, useJsonRpc } from "../hooks/useJsonRpc";
46
import notifications from "../notifications";
5-
import { SettingsItem } from "../routes/devices.$id.settings";
67

78
import Checkbox from "./Checkbox";
89
import { Button } from "./Button";

ui/src/components/UsbInfoSetting.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { useMemo , useCallback , useEffect, useState } from "react";
22

33
import { Button } from "@components/Button";
4-
4+
import { SettingsItem } from "@components/SettingsItem";
55

66
import { UsbConfigState } from "../hooks/stores";
77
import { JsonRpcResponse, useJsonRpc } from "../hooks/useJsonRpc";
88
import notifications from "../notifications";
9-
import { SettingsItem } from "../routes/devices.$id.settings";
109

1110
import { InputFieldWithLabel } from "./InputField";
1211
import { SelectMenuBasic } from "./SelectMenuBasic";

ui/src/routes/devices.$id.settings.access._index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { GridCard } from "@/components/Card";
99
import { Button, LinkButton } from "@/components/Button";
1010
import { InputFieldWithLabel } from "@/components/InputField";
1111
import { SelectMenuBasic } from "@/components/SelectMenuBasic";
12+
import { SettingsItem } from "@components/SettingsItem";
1213
import { SettingsSectionHeader } from "@/components/SettingsSectionHeader";
1314
import { useDeviceUiNavigation } from "@/hooks/useAppNavigation";
1415
import notifications from "@/notifications";
@@ -18,7 +19,6 @@ import { isOnDevice } from "@/main";
1819
import { TextAreaWithLabel } from "@components/TextArea";
1920

2021
import { LocalDevice } from "./devices.$id";
21-
import { SettingsItem } from "./devices.$id.settings";
2222
import { CloudState } from "./adopt";
2323

2424
export interface TLSState {

ui/src/routes/devices.$id.settings.advanced.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useCallback, useEffect, useState } from "react";
22

33
import { GridCard } from "@components/Card";
4+
import { SettingsItem } from "@components/SettingsItem";
45

56
import { Button } from "../components/Button";
67
import Checkbox from "../components/Checkbox";
@@ -12,8 +13,6 @@ import { JsonRpcResponse, useJsonRpc } from "../hooks/useJsonRpc";
1213
import { isOnDevice } from "../main";
1314
import notifications from "../notifications";
1415

15-
import { SettingsItem } from "./devices.$id.settings";
16-
1716
export default function SettingsAdvancedRoute() {
1817
const { send } = useJsonRpc();
1918

ui/src/routes/devices.$id.settings.appearance.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { useCallback, useState } from "react";
22

3+
import { SettingsItem } from "@components/SettingsItem";
4+
35
import { SettingsPageHeader } from "../components/SettingsPageheader";
46
import { SelectMenuBasic } from "../components/SelectMenuBasic";
57

6-
import { SettingsItem } from "./devices.$id.settings";
7-
88
export default function SettingsAppearanceRoute() {
99
const [currentTheme, setCurrentTheme] = useState(() => {
1010
return localStorage.theme || "system";

ui/src/routes/devices.$id.settings.general._index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
import { useState , useEffect } from "react";
33

4+
import { SettingsItem } from "@components/SettingsItem";
45
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
56

67
import { SettingsPageHeader } from "../components/SettingsPageheader";
@@ -10,7 +11,6 @@ import Checkbox from "../components/Checkbox";
1011
import { useDeviceUiNavigation } from "../hooks/useAppNavigation";
1112
import { useDeviceStore } from "../hooks/stores";
1213

13-
import { SettingsItem } from "./devices.$id.settings";
1414

1515
export default function SettingsGeneralRoute() {
1616
const { send } = useJsonRpc();

ui/src/routes/devices.$id.settings.hardware.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useEffect } from "react";
22

3+
import { SettingsItem } from "@components/SettingsItem";
34
import { SettingsPageHeader } from "@components/SettingsPageheader";
4-
import { SettingsItem } from "@routes/devices.$id.settings";
55
import { BacklightSettings, useSettingsStore } from "@/hooks/stores";
66
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
77
import { SelectMenuBasic } from "@components/SelectMenuBasic";

0 commit comments

Comments
 (0)