diff --git a/js/react/lib/components/input/index.ts b/js/react/lib/components/input/index.ts new file mode 100644 index 0000000..f144060 --- /dev/null +++ b/js/react/lib/components/input/index.ts @@ -0,0 +1,2 @@ +export * from "./input"; +export * from "./input.types"; diff --git a/js/react/lib/components/input/input.tsx b/js/react/lib/components/input/input.tsx new file mode 100644 index 0000000..2a701d4 --- /dev/null +++ b/js/react/lib/components/input/input.tsx @@ -0,0 +1,33 @@ +import clsx from "clsx"; +import { InputFieldProps } from "./input.types"; + +export function Input({ + errorMessage, + hasError = !!errorMessage, + icon, + disabled, + className, + ...props +}: InputFieldProps) { + return ( +
+
+ {icon && {icon}} + +
+ {hasError && errorMessage && ( + {errorMessage} + )} +
+ ); +} diff --git a/js/react/lib/components/input/input.types.ts b/js/react/lib/components/input/input.types.ts new file mode 100644 index 0000000..a747e26 --- /dev/null +++ b/js/react/lib/components/input/input.types.ts @@ -0,0 +1,7 @@ +import { InputHTMLAttributes, ReactNode } from "react"; + +export interface InputFieldProps extends InputHTMLAttributes { + hasError?: boolean; + errorMessage?: string; + icon?: ReactNode; +} diff --git a/js/react/lib/index.ts b/js/react/lib/index.ts index 501163c..6f9ff49 100644 --- a/js/react/lib/index.ts +++ b/js/react/lib/index.ts @@ -5,6 +5,7 @@ export * from "./components/contact-form"; export * from "./components/chip"; export * from "./components/tag"; export * from "./components/flap"; +export * from "./components/input"; export * from "./components/level"; export * from "./components/avatar"; export * from "./components/collaborators"; diff --git a/js/react/showcase/App.tsx b/js/react/showcase/App.tsx index 6872002..973d45e 100644 --- a/js/react/showcase/App.tsx +++ b/js/react/showcase/App.tsx @@ -5,6 +5,8 @@ import { Github, Tag, Telegram, + Input, + Location, Flap, Chip, Level, @@ -524,6 +526,31 @@ export function App() { + + + } placeholder="Input" /> +
:active), + &:has(> :focus) { + @apply border-primary-500; + } + + @variant has-disabled { + @apply cursor-not-allowed border-neutral-400 bg-neutral-100 text-neutral-600; + @apply dark:bg-neutral-900 dark:text-neutral-400; + } + } + + .rustlanges-input--error { + @apply border-error-600; + } + + .rustlanges-input__container { + @apply flex flex-col gap-1; + } + + .rustlanges-input__error { + @apply text-error-800 dark:text-error-300 mt-1 text-sm; + } + + .rustlanges-input__inner { + @apply w-full bg-transparent outline-none; + @apply placeholder:text-neutral-600 dark:placeholder:text-neutral-400; + @apply disabled:pointer-events-none disabled:placeholder:text-neutral-400 dark:disabled:placeholder:text-neutral-600; + } + + .rustlanges-input__icon { + @apply text-neutral-600; + + &:has(+ :disabled) { + @apply text-neutral-400; + } + } +}