mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-06-17 20:07:14 +02:00
chore: Upgrade UI vite and tailwind packages (#443)
* chore: Upgrade UI vite and tailwind packages Vite 5.2.0 -> 6.3.5 @vitejs/plugin-basic-ssl 1.2.0 -> 2.0.0 cva: 1.0.0-beta.1 -> 1.0.0-beta.3 focus-trap-react 10.2.3 -> 11.0.3 framer-motion 11.15.0 -> 12.11.0 @tailwindcss/postcss 4.1.6 @tailwindcss/vite 4.1.6 tailwind 3.4.17 -> 4.1.6 tailwind-merge 2.5.5 -> 3.3.0 Minor updates: @headlessui/react 2.2.2 -> 2.2.3 @types/react 19.1.3 -> 19.1.4 @types/react-dom 19.1.3 -> 19.1.5 @typescript-eslint/eslint-plugin 8.32.0 -> 8.32.1 @typescript-eslint/parser 8.32.0 -> 8.32.1 react-simple-keyboard 3.8.71 -> 3.8.72 The new version of vite required an Node 22.15 (since that's current LTS and node 21.x is EOL) The changes to css due to the tailwind 3 to 4 upgrade were done following [the upgrade guide](https://tailwindcss.com/docs/upgrade-guide#changes-from-v3) Done in this order (important): `shadow-sm` -> `shadow-xs` `shadow` -> `shadown-sm` `rounded` -> `rounded-sm` `outline-none` -> `outline-hidden` `32rem_32rem_at_center` -> `center_at_32rem_32rem` (revised order of gradient props) `ring-1 ring-black ring-opacity-5` -> `ring-1 ring-black/50` `flex-shrink-0` -> `shrink-0` `flex-grow-0` -> `grow-0` `outline outline-1` -> `outline-1` ALSO removed the **extra** `opacity-0` on the video element (trips up latest tailwind causing the video to be invisible) FocusTrap is now not exported as the default, so change those imports headlessui's Menu completely changed, so upgrade to the new syntax which necessitated a reorganization of the Header.tsx to enable the "menu" to still work * Update eslint config and fix errors
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
import { Fragment, useCallback } from "react";
|
||||
import { useCallback } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ArrowLeftEndOnRectangleIcon, ChevronDownIcon } from "@heroicons/react/16/solid";
|
||||
import { Menu, MenuButton } from "@headlessui/react";
|
||||
import { Button, Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
|
||||
import { LuMonitorSmartphone } from "react-icons/lu";
|
||||
|
||||
import Container from "@/components/Container";
|
||||
import Card from "@/components/Card";
|
||||
import { cx } from "@/cva.config";
|
||||
import { useHidStore, useRTCStore, useUserStore } from "@/hooks/stores";
|
||||
import LogoBlueIcon from "@/assets/logo-blue.svg";
|
||||
import LogoWhiteIcon from "@/assets/logo-white.svg";
|
||||
@@ -17,7 +16,7 @@ import { CLOUD_API, DEVICE_API } from "@/ui.config";
|
||||
import api from "../api";
|
||||
import { isOnDevice } from "../main";
|
||||
|
||||
import { Button, LinkButton } from "./Button";
|
||||
import { LinkButton } from "./Button";
|
||||
|
||||
interface NavbarProps {
|
||||
isLoggedIn: boolean;
|
||||
@@ -51,6 +50,10 @@ export default function DashboardNavbar({
|
||||
|
||||
const usbState = useHidStore(state => state.usbState);
|
||||
|
||||
// for testing
|
||||
//userEmail = "user@example.org";
|
||||
//picture = "https://placehold.co/32x32"
|
||||
|
||||
return (
|
||||
<div className="w-full select-none border-b border-b-slate-800/20 bg-white dark:border-b-slate-300/20 dark:bg-slate-900">
|
||||
<Container>
|
||||
@@ -78,86 +81,79 @@ export default function DashboardNavbar({
|
||||
</div>
|
||||
<div className="flex w-full items-center justify-end gap-x-2">
|
||||
<div className="flex shrink-0 items-center space-x-4">
|
||||
{showConnectionStatus && (
|
||||
<div className="hidden items-center gap-x-2 md:flex">
|
||||
<div className="w-[159px]">
|
||||
<PeerConnectionStatusCard
|
||||
state={peerConnectionState}
|
||||
title={kvmName}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden w-[159px] md:block">
|
||||
<USBStateStatus
|
||||
state={usbState}
|
||||
peerConnectionState={peerConnectionState}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
<hr className="h-[20px] w-[1px] border-none bg-slate-800/20 dark:bg-slate-300/20" />
|
||||
<Menu as="div" className="relative inline-block text-left">
|
||||
<div>
|
||||
<MenuButton as={Fragment}>
|
||||
<Button
|
||||
theme="blank"
|
||||
size="SM"
|
||||
text={
|
||||
<>
|
||||
{picture ? <></> : userEmail}
|
||||
<ChevronDownIcon className="h-4 w-4 shrink-0 text-slate-900 dark:text-white" />
|
||||
</>
|
||||
}
|
||||
LeadingIcon={({ className }) =>
|
||||
picture && (
|
||||
<img
|
||||
src={picture}
|
||||
alt="Avatar"
|
||||
className={cx(
|
||||
className,
|
||||
"h-8 w-8 rounded-full border-2 border-transparent transition-colors group-hover:border-blue-700",
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</MenuButton>
|
||||
<div className="hidden items-center gap-x-2 md:flex">
|
||||
{showConnectionStatus && (
|
||||
<>
|
||||
<div className="w-[159px]">
|
||||
<PeerConnectionStatusCard
|
||||
state={peerConnectionState}
|
||||
title={kvmName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Menu.Items className="absolute right-0 z-50 mt-2 w-56 origin-top-right focus:outline-none">
|
||||
<Card className="overflow-hidden">
|
||||
<div className="space-y-1 p-1 dark:text-white">
|
||||
{userEmail && (
|
||||
<div className="border-b border-b-slate-800/20 dark:border-slate-300/20">
|
||||
<Menu.Item>
|
||||
<div className="p-2">
|
||||
<div className="font-display text-xs">Logged in as</div>
|
||||
<div className="w-[200px] truncate font-display text-sm font-semibold">
|
||||
{userEmail}
|
||||
</div>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<Menu.Item>
|
||||
<div onClick={onLogout}>
|
||||
<button className="block w-full">
|
||||
<div className="flex items-center gap-x-2 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-slate-100 dark:hover:bg-slate-700">
|
||||
<ArrowLeftEndOnRectangleIcon className="h-4 w-4" />
|
||||
<div className="font-display">Log out</div>
|
||||
<div className="hidden w-[159px] md:block">
|
||||
<USBStateStatus
|
||||
state={usbState}
|
||||
peerConnectionState={peerConnectionState}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
<hr className="h-[20px] w-[1px] border-none bg-slate-800/20 dark:bg-slate-300/20" />
|
||||
<div className="relative inline-block text-left">
|
||||
<Menu>
|
||||
<MenuButton>
|
||||
<Button className="flex items-center gap-x-3 rounded-md border bg-white dark:border-slate-600 dark:bg-slate-800 dark:text-white border-slate-800/20 px-2 py-1.5">
|
||||
{picture
|
||||
? (
|
||||
<img
|
||||
src={picture}
|
||||
alt="Avatar"
|
||||
className="size-6 rounded-full border-2 border-transparent transition-colors group-hover:border-blue-700"
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<span className="max-w-[200px] text-sm/6 font-display font-semibold truncate">
|
||||
{userEmail}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
<ChevronDownIcon className="size-4 shrink-0 text-slate-900 dark:text-white" />
|
||||
</Button>
|
||||
</MenuButton>
|
||||
<MenuItems
|
||||
transition
|
||||
anchor="bottom end"
|
||||
className="right-0 mt-1 w-56 origin-top-right data-closed:opacity-0 focus:outline-hidden">
|
||||
<MenuItem>
|
||||
<Card className="overflow-hidden">
|
||||
<div className="space-y-1 p-1 dark:text-white">
|
||||
{userEmail && (
|
||||
<div className="border-b border-b-slate-800/20 dark:border-slate-300/20">
|
||||
<div className="p-2">
|
||||
<div className="font-display text-xs">Logged in as</div>
|
||||
<div className="max-w-[200px] truncate font-display text-sm font-semibold">
|
||||
{userEmail}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-1 p-1 dark:text-white" onClick={onLogout}>
|
||||
<button className="group flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors hover:bg-slate-100 dark:hover:bg-slate-700">
|
||||
<ArrowLeftEndOnRectangleIcon className="size-4" />
|
||||
<div className="font-display">Log out</div>
|
||||
</button>
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</Menu.Items>
|
||||
</Menu>
|
||||
</>
|
||||
) : null}
|
||||
</Card>
|
||||
</MenuItem>
|
||||
</MenuItems>
|
||||
</Menu>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user