Files
kvm/ui/src/components/TextArea.tsx
Marc Brooks 7ccb8e617c 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
2025-05-15 14:21:03 +02:00

58 lines
1.8 KiB
TypeScript

import React, { JSX } from "react";
import clsx from "clsx";
import FieldLabel from "@/components/FieldLabel";
import { FieldError } from "@/components/InputField";
import Card from "@/components/Card";
import { cx } from "@/cva.config";
type TextAreaProps = JSX.IntrinsicElements["textarea"] & {
error?: string | null;
};
const TextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(
function TextArea(props, ref) {
return (
<Card
className={cx(
"relative w-full",
"invalid-within::ring-2 invalid-within::ring-red-600 invalid-within::ring-offset-2",
"focus-within:border-slate-300 focus-within:outline-hidden focus-within:ring-1 focus-within:ring-blue-700 dark:focus-within:border-slate-600",
)}
>
<textarea
ref={ref}
{...props}
id="asd"
className={clsx(
"block w-full rounded-sm border-transparent bg-transparent text-black placeholder:text-slate-300 focus:ring-0 disabled:pointer-events-none disabled:select-none disabled:bg-slate-50 disabled:text-slate-300 dark:text-white dark:placeholder:text-slate-500 dark:disabled:bg-slate-800 sm:text-sm",
props.className,
)}
/>
</Card>
);
},
);
type TextAreaWithLabelProps = {
label: string | React.ReactNode;
id?: string;
description?: string;
error?: string | null;
} & React.ComponentProps<typeof TextArea>;
export const TextAreaWithLabel = React.forwardRef<
HTMLTextAreaElement,
TextAreaWithLabelProps
>(function TextAreaWithLabel({ label, error, id, description, ...props }, ref) {
return (
<div className="space-y-1">
<FieldLabel label={label} id={id} description={description} />
<TextArea ref={ref} {...props} />
{error && <FieldError error={error} />}
</div>
);
});
export default TextArea;