refactor: Migrate from tailwind.js config to Tailwind CSS config (#451)

* refactor: Migrate from tailwind.js config to Tailwind CSS configuration and improve component styling

- Removed extensive theme and animation configurations from tailwind.config.js, migrating them to index.css for better organization.
- Updated components to utilize CSS variables for grid layouts and animations, enhancing maintainability.
- Adjusted various components to reflect the new CSS structure, ensuring consistent styling across the application.
- Improved accessibility and responsiveness in several UI components, including headers and popovers.
- Fixed minor styling issues and optimized class usage for better performance.

* style: use default tailwindcss/forms options

* refactor(Header): remove unused LuUser icon import
This commit is contained in:
Adam Shiervani
2025-05-15 17:13:16 +02:00
committed by GitHub
parent c9dd3cd926
commit baf85dcbec
22 changed files with 233 additions and 185 deletions

View File

@@ -71,7 +71,7 @@ export default function DevicesIdDeregister() {
const error = useActionData() as { message: string };
return (
<div className="grid min-h-screen grid-rows-layout">
<div className="grid min-h-screen grid-rows-(--grid-layout)">
<DashboardNavbar
isLoggedIn={!!user}
primaryLinks={[{ title: "Cloud Devices", to: "/devices" }]}

View File

@@ -75,7 +75,7 @@ export default function DeviceIdRename() {
const error = useActionData() as { message: string };
return (
<div className="grid min-h-screen grid-rows-layout">
<div className="grid min-h-screen grid-rows-(--grid-layout)">
<DashboardNavbar
isLoggedIn={!!user}
primaryLinks={[{ title: "Cloud Devices", to: "/devices" }]}

View File

@@ -56,7 +56,7 @@ export default function SetupRoute() {
return (
<>
<GridBackground />
<div className="grid min-h-screen grid-rows-layout">
<div className="grid min-h-screen grid-rows-(--grid-layout)">
<SimpleNavbar />
<Container>
<div className="flex items-center justify-center w-full h-full isolate">

View File

@@ -795,7 +795,7 @@ export default function KvmIdRoute() {
</div>
</FocusTrap>
<div className="grid h-full select-none grid-rows-headerBody">
<div className="grid h-full grid-rows-(--grid-headerBody) select-none">
<DashboardNavbar
primaryLinks={isOnDevice ? [] : [{ title: "Cloud Devices", to: "/devices" }]}
showConnectionStatus={true}
@@ -809,7 +809,7 @@ export default function KvmIdRoute() {
<WebRTCVideo />
<div
style={{ animationDuration: "500ms" }}
className="pointer-events-none absolute inset-0 flex animate-slideUpFade items-center justify-center p-4"
className="animate-slideUpFade pointer-events-none absolute inset-0 flex items-center justify-center p-4"
>
<div className="relative h-full max-h-[720px] w-full max-w-[1280px] rounded-md">
{!!ConnectionStatusElement && ConnectionStatusElement}

View File

@@ -8,7 +8,7 @@ export default function DevicesAlreadyAdopted() {
<>
<GridBackground />
<div className="grid min-h-screen grid-rows-layout">
<div className="grid min-h-screen grid-rows-(--grid-layout)">
<SimpleNavbar />
<Container>
<div className="flex items-center justify-center w-full h-full isolate">

View File

@@ -40,7 +40,7 @@ export default function DevicesRoute() {
useInterval(revalidate.revalidate, 4000);
return (
<div className="relative h-full">
<div className="grid h-full select-none grid-rows-headerBody">
<div className="grid h-full select-none grid-rows-(--grid-headerBody)">
<DashboardNavbar
isLoggedIn={!!user}
primaryLinks={[{ title: "Cloud Devices", to: "/devices" }]}
@@ -102,4 +102,4 @@ export default function DevicesRoute() {
);
}
DevicesRoute.loader = loader;
DevicesRoute.loader = loader;

View File

@@ -56,7 +56,7 @@ export default function LoginLocalRoute() {
return (
<>
<GridBackground />
<div className="grid min-h-screen grid-rows-layout">
<div className="grid min-h-screen grid-rows-(--grid-layout)">
<SimpleNavbar />
<Container>
<div className="isolate flex h-full w-full items-center justify-center">

View File

@@ -14,7 +14,6 @@ import api from "../api";
import { DeviceStatus } from "./welcome-local";
const loader = async () => {
const res = await api
.GET(`${DEVICE_API}/device/status`)
@@ -59,18 +58,24 @@ export default function WelcomeLocalModeRoute() {
<GridBackground />
<div className="grid min-h-screen">
<Container>
<div className="flex items-center justify-center w-full h-full isolate">
<div className="isolate flex h-full w-full items-center justify-center">
<div className="max-w-xl space-y-8">
<div className="flex items-center justify-center animate-fadeIn">
<img src={LogoWhiteIcon} alt="" className="-ml-4 h-[32px] hidden dark:block" />
<div className="animate-fadeIn flex items-center justify-center opacity-0">
<img
src={LogoWhiteIcon}
alt=""
className="-ml-4 hidden h-[32px] dark:block"
/>
<img src={LogoBlueIcon} alt="" className="-ml-4 h-[32px] dark:hidden" />
</div>
<div
className="space-y-2 text-center animate-fadeIn"
className="animate-fadeIn space-y-2 text-center opacity-0"
style={{ animationDelay: "200ms" }}
>
<h1 className="text-4xl font-semibold text-black dark:text-white">Local Authentication Method</h1>
<h1 className="text-4xl font-semibold text-black dark:text-white">
Local Authentication Method
</h1>
<p className="font-medium text-slate-600 dark:text-slate-400">
Select how you{"'"}d like to secure your JetKVM device locally.
</p>
@@ -78,7 +83,7 @@ export default function WelcomeLocalModeRoute() {
<Form method="POST" className="space-y-8">
<div
className="grid grid-cols-1 gap-6 animate-fadeIn sm:grid-cols-2"
className="animate-fadeIn grid grid-cols-1 gap-6 opacity-0 sm:grid-cols-2"
style={{ animationDelay: "400ms" }}
>
{["password", "noPassword"].map(mode => (
@@ -90,14 +95,14 @@ export default function WelcomeLocalModeRoute() {
})}
>
<div
className="relative flex flex-col items-center p-6 cursor-pointer select-none"
className="relative flex cursor-pointer flex-col items-center p-6 select-none"
onClick={() => setSelectedMode(mode as "password" | "noPassword")}
>
<div className="space-y-0 text-center">
<h3 className="text-base font-bold text-black dark:text-white">
{mode === "password" ? "Password protected" : "No Password"}
</h3>
<p className="mt-2 text-sm text-center text-gray-600 dark:text-gray-400">
<p className="mt-2 text-center text-sm text-gray-600 dark:text-gray-400">
{mode === "password"
? "Secure your device with a password for added protection."
: "Quick access without password authentication."}
@@ -111,7 +116,7 @@ export default function WelcomeLocalModeRoute() {
onChange={() => {
setSelectedMode(mode as "password" | "noPassword");
}}
className="absolute w-4 h-4 text-blue-600 right-2 top-2"
className="absolute top-2 right-2 h-4 w-4 text-blue-600"
/>
</div>
</GridCard>
@@ -120,7 +125,7 @@ export default function WelcomeLocalModeRoute() {
{actionData?.error && (
<p
className="text-sm text-center text-red-600 dark:text-red-400 animate-fadeIn"
className="animate-fadeIn text-center text-sm text-red-600 opacity-0 dark:text-red-400"
style={{ animationDelay: "500ms" }}
>
{actionData.error}
@@ -128,7 +133,7 @@ export default function WelcomeLocalModeRoute() {
)}
<div
className="max-w-sm mx-auto animate-fadeIn"
className="animate-fadeIn mx-auto max-w-sm opacity-0"
style={{ animationDelay: "500ms" }}
>
<Button
@@ -144,7 +149,7 @@ export default function WelcomeLocalModeRoute() {
</Form>
<p
className="max-w-md mx-auto text-xs text-center animate-fadeIn text-slate-500 dark:text-slate-400"
className="animate-fadeIn mx-auto max-w-md text-center text-xs text-slate-500 opacity-0 dark:text-slate-400"
style={{ animationDelay: "600ms" }}
>
You can always change your authentication method later in the settings.

View File

@@ -69,28 +69,34 @@ export default function WelcomeLocalPasswordRoute() {
<GridBackground />
<div className="grid min-h-screen">
<Container>
<div className="flex items-center justify-center w-full h-full isolate">
<div className="isolate flex h-full w-full items-center justify-center">
<div className="max-w-2xl space-y-8">
<div className="flex items-center justify-center animate-fadeIn">
<img src={LogoWhiteIcon} alt="" className="-ml-4 h-[32px] hidden dark:block" />
<div className="animate-fadeIn flex items-center justify-center opacity-0">
<img
src={LogoWhiteIcon}
alt=""
className="-ml-4 hidden h-[32px] dark:block"
/>
<img src={LogoBlueIcon} alt="" className="-ml-4 h-[32px] dark:hidden" />
</div>
<div
className="space-y-2 text-center animate-fadeIn"
className="animate-fadeIn space-y-2 text-center opacity-0"
style={{ animationDelay: "200ms" }}
>
<h1 className="text-4xl font-semibold text-black dark:text-white">Set a Password</h1>
<h1 className="text-4xl font-semibold text-black dark:text-white">
Set a Password
</h1>
<p className="font-medium text-slate-600 dark:text-slate-400">
Create a strong password to secure your JetKVM device locally.
</p>
</div>
<Fieldset className="space-y-12">
<Form method="POST" className="max-w-sm mx-auto space-y-4">
<Form method="POST" className="mx-auto max-w-sm space-y-4">
<div className="space-y-4">
<div
className="animate-fadeIn"
className="animate-fadeIn opacity-0"
style={{ animationDelay: "400ms" }}
>
<InputFieldWithLabel
@@ -106,21 +112,21 @@ export default function WelcomeLocalPasswordRoute() {
onClick={() => setShowPassword(false)}
className="pointer-events-auto"
>
<LuEye className="w-4 h-4 cursor-pointer text-slate-500 dark:text-slate-400" />
<LuEye className="h-4 w-4 cursor-pointer text-slate-500 dark:text-slate-400" />
</div>
) : (
<div
onClick={() => setShowPassword(true)}
className="pointer-events-auto"
>
<LuEyeOff className="w-4 h-4 cursor-pointer text-slate-500 dark:text-slate-400" />
<LuEyeOff className="h-4 w-4 cursor-pointer text-slate-500 dark:text-slate-400" />
</div>
)
}
/>
</div>
<div
className="animate-fadeIn"
className="animate-fadeIn opacity-0"
style={{ animationDelay: "400ms" }}
>
<InputFieldWithLabel
@@ -137,7 +143,7 @@ export default function WelcomeLocalPasswordRoute() {
{actionData?.error && <p className="text-sm text-red-600">{}</p>}
<div
className="animate-fadeIn"
className="animate-fadeIn opacity-0"
style={{ animationDelay: "600ms" }}
>
<Button
@@ -153,7 +159,7 @@ export default function WelcomeLocalPasswordRoute() {
</Fieldset>
<p
className="max-w-md text-xs text-center animate-fadeIn text-slate-500 dark:text-slate-400"
className="animate-fadeIn max-w-md text-center text-xs text-slate-500 opacity-0 dark:text-slate-400"
style={{ animationDelay: "800ms" }}
>
This password will be used to secure your device data and protect against

View File

@@ -13,8 +13,6 @@ import { DEVICE_API } from "@/ui.config";
import api from "../api";
export interface DeviceStatus {
isSetup: boolean;
}
@@ -43,19 +41,24 @@ export default function WelcomeRoute() {
<div className="grid min-h-screen">
{imageLoaded && (
<Container>
<div className="flex items-center justify-center w-full h-full isolate">
<div className="isolate flex h-full w-full items-center justify-center">
<div className="max-w-3xl text-center">
<div className="space-y-8">
<div className="space-y-4">
<div className="flex items-center justify-center animate-fadeIn animation-delay-1000">
<img src={LogoWhiteIcon} alt="JetKVM Logo" className="h-[32px] hidden dark:block" />
<img src={LogoBlueIcon} alt="JetKVM Logo" className="h-[32px] dark:hidden" />
<div className="animate-fadeIn animation-delay-1000 flex items-center justify-center opacity-0">
<img
src={LogoWhiteIcon}
alt="JetKVM Logo"
className="hidden h-[32px] dark:block"
/>
<img
src={LogoBlueIcon}
alt="JetKVM Logo"
className="h-[32px] dark:hidden"
/>
</div>
<div
className="space-y-1 animate-fadeIn"
style={{ animationDelay: "1500ms" }}
>
<div className="animate-fadeIn animation-delay-1500 space-y-1 opacity-0">
<h1 className="text-4xl font-semibold text-black dark:text-white">
Welcome to JetKVM
</h1>
@@ -69,22 +72,19 @@ export default function WelcomeRoute() {
<img
src={DeviceImage}
alt="JetKVM Device"
className="animation-delay-0 max-w-md scale-[0.98] animate-fadeInScaleFloat transition-all duration-1000 ease-out"
className="animation-delay-300 animate-fadeInScaleFloat max-w-md scale-[0.98] opacity-0 transition-all duration-1000 ease-out"
/>
</div>
</div>
<div className="-mt-8 space-y-4">
<p
style={{ animationDelay: "2000ms" }}
className="max-w-lg mx-auto text-lg animate-fadeIn text-slate-700 dark:text-slate-300"
className="animate-fadeIn mx-auto max-w-lg text-lg text-slate-700 opacity-0 dark:text-slate-300"
>
JetKVM combines powerful hardware with intuitive software to provide a
seamless remote control experience.
</p>
<div
style={{ animationDelay: "2300ms" }}
className="animate-fadeIn"
>
<div className="animate-fadeIn animation-delay-2300 opacity-0">
<LinkButton
size="LG"
theme="light"