From fc0060136f918a750eb0e88965d0c212c54f10b2 Mon Sep 17 00:00:00 2001 From: Ilya Topilskii Date: Tue, 3 Dec 2024 16:07:58 +0100 Subject: [PATCH] fix: fixes after review --- packages/ui/src/components/button.tsx | 12 +- packages/ui/src/components/card.tsx | 8 +- packages/ui/src/components/control-group.tsx | 20 +++ .../ui/src/components/form-error-message.tsx | 37 +++++ packages/ui/src/components/index.ts | 2 + packages/ui/src/components/input-otp.tsx | 2 +- packages/ui/src/components/input.tsx | 157 ++++++++---------- packages/ui/src/components/label.tsx | 44 +++-- .../src/views/auth/components/agreements.tsx | 6 +- .../auth/components/animated-harness-logo.tsx | 5 +- .../src/views/auth/forgot-password-page.tsx | 17 +- .../ui/src/views/auth/new-password-page.tsx | 31 ++-- packages/ui/src/views/auth/otp-page.tsx | 14 +- packages/ui/src/views/auth/signin-page.tsx | 33 ++-- packages/ui/src/views/auth/signup-page.tsx | 95 ++++++----- 15 files changed, 279 insertions(+), 204 deletions(-) create mode 100644 packages/ui/src/components/control-group.tsx create mode 100644 packages/ui/src/components/form-error-message.tsx diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index d64df2e74..44023080c 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -10,11 +10,11 @@ const buttonVariants = cva( { variants: { variant: { - default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90', - destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90', - outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground', - secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80', - tertiary: 'bg-tertiary text-secondary-foreground shadow-sm hover:bg-tertiary/80', + default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm', + outline: 'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm', + tertiary: 'bg-tertiary text-secondary-foreground hover:bg-tertiary/80 shadow-sm', ghost: 'hover:bg-background-12 hover:text-accent-foreground', link: 'text-primary underline-offset-4 hover:underline', link_accent: 'text-foreground-accent underline-offset-4 hover:underline', @@ -34,7 +34,7 @@ const buttonVariants = cva( }, borderRadius: { default: '', - full: 'rounded-full', + full: 'rounded-full focus-visible:rounded-full', none: 'rounded-none' }, theme: { diff --git a/packages/ui/src/components/card.tsx b/packages/ui/src/components/card.tsx index e21e737c9..758e35e3b 100644 --- a/packages/ui/src/components/card.tsx +++ b/packages/ui/src/components/card.tsx @@ -3,7 +3,7 @@ import { forwardRef, HTMLAttributes } from 'react' import { cn } from '@utils/cn' import { cva, type VariantProps } from 'class-variance-authority' -const cardVariants = cva('rounded-lg border bg-card text-card-foreground shadow', { +const cardVariants = cva('bg-card text-card-foreground rounded-lg border shadow', { variants: { variant: { default: '', @@ -19,7 +19,7 @@ export interface CardProps extends HTMLAttributes, VariantProps< width?: 'auto' | 'full' | 'screen' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | string } -const widthClasses = { +const widthVariants = { auto: 'w-auto', full: 'w-full', screen: 'w-screen', @@ -33,9 +33,9 @@ const widthClasses = { } const Card = forwardRef(({ variant, className, width = 'auto', ...props }, ref) => { - const widthClass = widthClasses[width as keyof typeof widthClasses] || width + const widthClassName = widthVariants[width as keyof typeof widthVariants] || width - return
+ return
}) Card.displayName = 'Card' diff --git a/packages/ui/src/components/control-group.tsx b/packages/ui/src/components/control-group.tsx new file mode 100644 index 000000000..f06ed0821 --- /dev/null +++ b/packages/ui/src/components/control-group.tsx @@ -0,0 +1,20 @@ +import { HTMLAttributes } from 'react' + +import { cn } from '@utils/cn' + +interface ControlGroupProps extends HTMLAttributes { + type?: 'button' | 'input' +} + +export function ControlGroup({ children, type, className, ...props }: ControlGroupProps) { + return ( +
+ {children} +
+ ) +} diff --git a/packages/ui/src/components/form-error-message.tsx b/packages/ui/src/components/form-error-message.tsx new file mode 100644 index 000000000..a76f89c1e --- /dev/null +++ b/packages/ui/src/components/form-error-message.tsx @@ -0,0 +1,37 @@ +import { HTMLAttributes } from 'react' + +import { cn } from '@utils/cn' + +import { Text } from './text' + +export enum ErrorMessageTheme { + SUCCESS = 'success', + WARNING = 'warning', + ERROR = 'error', + DEFAULT = 'default' +} + +interface FormErrorMessageProps extends HTMLAttributes { + theme: ErrorMessageTheme +} + +const themeClassMap: Record = { + [ErrorMessageTheme.SUCCESS]: 'text-success', + [ErrorMessageTheme.WARNING]: 'text-warning', + [ErrorMessageTheme.ERROR]: 'text-foreground-danger', + [ErrorMessageTheme.DEFAULT]: 'text-tertiary-background' +} + +export function FormErrorMessage({ children, theme, className }: FormErrorMessageProps) { + const textClass = themeClassMap[theme] + const role = theme === ErrorMessageTheme.ERROR ? 'alert' : 'status' + const ariaLive = theme === ErrorMessageTheme.ERROR ? 'assertive' : 'polite' + + return ( +
+ + {children} + +
+ ) +} diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index 1ab3d3019..77e1f4af8 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -36,6 +36,8 @@ export * from './dialog' export * from './path-breadcrumbs' export * from './card' export * from './input-otp' +export * from './control-group' +export * from './form-error-message' export * as ShaBadge from './sha-badge' export * as ListActions from './list-actions' diff --git a/packages/ui/src/components/input-otp.tsx b/packages/ui/src/components/input-otp.tsx index 260892331..9c61e65b8 100644 --- a/packages/ui/src/components/input-otp.tsx +++ b/packages/ui/src/components/input-otp.tsx @@ -49,7 +49,7 @@ const InputOTPSlot = forwardRef(({ index, cla {char} {hasFakeCaret && (
-
+
)}
diff --git a/packages/ui/src/components/input.tsx b/packages/ui/src/components/input.tsx index 209d1e721..d806bdeda 100644 --- a/packages/ui/src/components/input.tsx +++ b/packages/ui/src/components/input.tsx @@ -1,119 +1,94 @@ -import { forwardRef, InputHTMLAttributes } from 'react' +import { forwardRef, InputHTMLAttributes, ReactNode } from 'react' -import { cva, VariantProps } from 'class-variance-authority' +import { cva, type VariantProps } from 'class-variance-authority' import { cn } from '../utils/cn' -import { Text } from './' +import { ControlGroup } from './control-group' +import { ErrorMessageTheme, FormErrorMessage } from './form-error-message' +import { Label } from './label' +import { Text } from './text' export interface BaseInputProps extends Omit, 'size'>, - VariantProps { - wrapperClassName?: string - error?: string -} + VariantProps {} -const inputVariants = cva( - 'remove-autocomplete-styles bg-transparent placeholder:text-foreground-5 text-foreground-1 px-3 py-1', - { - variants: { - variant: { - default: - 'flex h-9 w-full rounded border text-sm shadow-sm transition-colors file:border-0 focus-visible:outline-none file:bg-transparent file:text-sm file:font-medium placeholder:text-foreground-4 disabled:cursor-not-allowed disabled:opacity-50', - extended: 'grow border-none focus-visible:outline-none' - }, - theme: { - default: 'border-borders-2 focus-visible:border-borders-3', - danger: 'border-borders-danger' - } +const inputVariants = cva('text-foreground-1 bg-transparent px-2.5 py-1 disabled:cursor-not-allowed', { + variants: { + variant: { + default: + 'placeholder:text-foreground-4 flex w-full rounded border text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:rounded focus-visible:outline-none', + extended: 'grow border-none focus-visible:outline-none' + }, + size: { + 32: 'h-8', + 36: 'h-9' + }, + theme: { + default: + 'border-borders-2 focus-visible:border-borders-3 disabled:border-borders-1 disabled:placeholder:text-foreground-9', + danger: 'border-borders-danger' } + }, + defaultVariants: { + variant: 'default', + theme: 'default', + size: 32 } -) +}) const BaseInput = forwardRef( - ({ className, type, variant = 'default', theme = 'default', error, wrapperClassName, ...props }, ref) => { - return ( -
- - {error && ( - - {error} - - )} -
- ) + ({ className, type, variant, size, theme, ...props }, ref) => { + return } ) + BaseInput.displayName = 'BaseInput' -export interface ExtendedInputProps extends BaseInputProps { - left?: React.ReactNode - leftStyle?: boolean - leftClassName?: string - right?: React.ReactNode - rightStyle?: boolean - rightClassName?: string +interface InputError { + theme: ErrorMessageTheme + message?: string } -const containerClassName = - 'remove-autocomplete-styles flex h-9 w-full rounded border border-input text-sm shadow-sm transition-colors placeholder:text-foreground-4 focus-within:outline-none focus-within:ring-1 focus-within:ring-ring disabled:cursor-not-allowed disabled:opacity-50' -const leftRightCommonClassName = 'flex items-center text-muted-foreground' +interface InputProps extends BaseInputProps { + label?: string + caption?: ReactNode + error?: InputError + optional?: boolean + wrapperClassName?: string +} -const ExtendedInput = forwardRef( - ({ className, type, left, leftStyle, leftClassName, right, rightStyle, rightClassName, ...props }, ref) => { +const Input = forwardRef( + ({ label, caption, error, id, theme, disabled, optional, className, wrapperClassName, ...props }, ref) => { return ( -
- {left && ( -
- {left} -
+ + {label && ( + + )} + + {error && ( + + {error.message} + )} - - {right && ( -
- {right} -
+ {caption && ( + + {caption} + )} -
+ ) } ) -ExtendedInput.displayName = 'ExtendedInput' -interface InputProps extends ExtendedInputProps {} - -const Input = forwardRef(({ left, right, ...props }, ref) => { - if (left || right) { - return - } - return -}) Input.displayName = 'Input' export { Input } diff --git a/packages/ui/src/components/label.tsx b/packages/ui/src/components/label.tsx index d1aeaf8b1..1bb52ba5b 100644 --- a/packages/ui/src/components/label.tsx +++ b/packages/ui/src/components/label.tsx @@ -1,33 +1,49 @@ // ToDo: Need to be reviewed by the XD team -import { ComponentPropsWithoutRef, ElementRef, forwardRef } from 'react' +import { ComponentPropsWithoutRef, ElementRef, forwardRef, PropsWithChildren } from 'react' import * as LabelPrimitive from '@radix-ui/react-label' import { cn } from '@utils/cn' import { cva, type VariantProps } from 'class-variance-authority' -const labelVariants = cva('block leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', { +const labelVariants = cva('peer-disabled:cursor-not-allowed peer-disabled:opacity-70', { variants: { variant: { - default: 'text-sm leading-none', - sm: 'text-xs font-light' + default: 'text-sm font-normal leading-none' + }, + color: { + 'foreground-1': 'text-foreground-1', + 'foreground-2': 'text-foreground-2', + 'foreground-5': 'text-foreground-5', + 'foreground-9': 'text-foreground-9' } }, defaultVariants: { - variant: 'default' + variant: 'default', + color: 'foreground-1' } }) -const Label = forwardRef< +const LabelRoot = forwardRef< ElementRef, - ComponentPropsWithoutRef & VariantProps ->(({ className, variant, ...props }, ref) => ( - + Omit, 'color'> & VariantProps +>(({ className, variant, color, ...props }, ref) => ( + )) -Label.displayName = LabelPrimitive.Root.displayName +LabelRoot.displayName = LabelPrimitive.Root.displayName + +interface LabelProps extends VariantProps, PropsWithChildren { + htmlFor?: string + optional?: boolean + className?: string +} + +const Label = ({ htmlFor, optional, color, variant, children, className }: LabelProps) => { + return ( + + {children} {optional && (optional)} + + ) +} export { Label } diff --git a/packages/ui/src/views/auth/components/agreements.tsx b/packages/ui/src/views/auth/components/agreements.tsx index 52d093c40..7f99dadd9 100644 --- a/packages/ui/src/views/auth/components/agreements.tsx +++ b/packages/ui/src/views/auth/components/agreements.tsx @@ -1,20 +1,20 @@ import { Link } from 'react-router-dom' -import { Text } from '../../../components' +import { Text } from '@/components' export function Agreements() { return ( By joining, you agree to{' '} Terms of Service {' '} and  Privacy Policy diff --git a/packages/ui/src/views/auth/components/animated-harness-logo.tsx b/packages/ui/src/views/auth/components/animated-harness-logo.tsx index 5d66e7005..092e6a90c 100644 --- a/packages/ui/src/views/auth/components/animated-harness-logo.tsx +++ b/packages/ui/src/views/auth/components/animated-harness-logo.tsx @@ -1,7 +1,6 @@ +import { Icon } from '@/components' import { cn } from '@utils/cn' -import { Icon } from '../../../components' - interface AnimatedHarnessLogoProps { theme: 'error' | 'green' | 'blue' } @@ -37,7 +36,7 @@ export function AnimatedHarnessLogo({ theme }: AnimatedHarnessLogoProps) { shadowBackground )} /> -
+
@@ -85,16 +85,19 @@ export function ForgotPasswordPage({ isLoading, onSubmit, error }: ForgotPasswor
-