mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-05-11 16:49:28 -04:00
Redesign input and empty state components: improve search input interactions with clear button and icons, update compatibility questions empty state styling, and adjust profile form input widths and button properties for consistency and usability.
This commit is contained in:
@@ -313,7 +313,14 @@ export function CompatibilityQuestionsDisplay(props: {
|
||||
)
|
||||
})}
|
||||
{shownAnswers.length === 0 && (
|
||||
<div className="text-ink-500">{t('answers.display.none', 'None')}</div>
|
||||
<Col className="items-center py-8 text-center">
|
||||
<div className="text-ink-600 mb-2">
|
||||
{t('answers.display.no_results', 'No questions match your search')}
|
||||
</div>
|
||||
<div className="text-sm text-ink-500">
|
||||
{t('answers.display.try_different', 'Try adjusting your search or filters')}
|
||||
</div>
|
||||
</Col>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -387,6 +387,7 @@ export const OptionalProfileUserForm = (props: {
|
||||
<label className={clsx(labelClassName)}>{t('profile.optional.age', 'Age')}</label>
|
||||
<Input
|
||||
type="number"
|
||||
className={'!w-24'}
|
||||
placeholder={t('profile.optional.age', 'Age')}
|
||||
value={profile['age'] ?? undefined}
|
||||
min={18}
|
||||
@@ -422,7 +423,7 @@ export const OptionalProfileUserForm = (props: {
|
||||
const heightInInches = Number(e.target.value || 0) * 12 + (heightInches ?? 0)
|
||||
setProfile('height_in_inches', heightInInches)
|
||||
}}
|
||||
className={'w-20'}
|
||||
className={'!w-20'}
|
||||
value={typeof heightFeet === 'number' && heightFeet ? Math.floor(heightFeet) : ''}
|
||||
min={0}
|
||||
step={1}
|
||||
@@ -437,7 +438,7 @@ export const OptionalProfileUserForm = (props: {
|
||||
const heightInInches = Number(e.target.value || 0) + 12 * (heightFeet ?? 0)
|
||||
setProfile('height_in_inches', heightInInches)
|
||||
}}
|
||||
className={'w-20'}
|
||||
className={'!w-20'}
|
||||
value={
|
||||
typeof heightInches === 'number' && heightInches ? Math.floor(heightInches) : ''
|
||||
}
|
||||
@@ -462,7 +463,7 @@ export const OptionalProfileUserForm = (props: {
|
||||
setProfile('height_in_inches', totalInches)
|
||||
}
|
||||
}}
|
||||
className={'w-24'}
|
||||
className={'!w-24'}
|
||||
value={
|
||||
heightFeet !== undefined && profile['height_in_inches']
|
||||
? Math.round(profile['height_in_inches'] * 2.54)
|
||||
@@ -1187,7 +1188,8 @@ export const OptionalProfileUserForm = (props: {
|
||||
disabled={isSubmitting || uploadingImages}
|
||||
loading={isSubmitting}
|
||||
onClick={handleSubmit}
|
||||
color={'gray'}
|
||||
size={'xl'}
|
||||
color={'primary'}
|
||||
>
|
||||
{buttonLabel ?? t('common.next', 'Next')}
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import clsx from 'clsx'
|
||||
import {ComponentPropsWithoutRef, forwardRef, Ref} from 'react'
|
||||
import {Search, X} from 'lucide-react'
|
||||
import {ComponentPropsWithoutRef, forwardRef, Ref, useState} from 'react'
|
||||
import {Row} from 'web/components/layout/row'
|
||||
|
||||
/** Text input. Wraps html `<input>` */
|
||||
@@ -11,21 +12,40 @@ export const Input = forwardRef(
|
||||
} & ComponentPropsWithoutRef<'input'>,
|
||||
ref: Ref<HTMLInputElement>,
|
||||
) => {
|
||||
const {error, searchIcon, className, ...rest} = props
|
||||
const {error, searchIcon, className, value, onChange, ...rest} = props
|
||||
const [hasValue, setHasValue] = useState(!!value)
|
||||
|
||||
const rowClassName = clsx(
|
||||
'bg-canvas-50 h-12 rounded-xl border border-canvas-200 px-4 shadow-sm transition-colors items-center gap-2',
|
||||
className,
|
||||
)
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setHasValue(!!e.target.value)
|
||||
onChange?.(e)
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
setHasValue(false)
|
||||
// Trigger onChange with empty value
|
||||
const syntheticEvent = {
|
||||
target: {value: ''},
|
||||
} as React.ChangeEvent<HTMLInputElement>
|
||||
onChange?.(syntheticEvent)
|
||||
}
|
||||
|
||||
const rowClassName =
|
||||
'bg-canvas-50 h-12 rounded-xl border border-canvas-200 px-4 shadow-sm transition-colors items-center gap-2'
|
||||
const elem = (
|
||||
<input
|
||||
ref={ref}
|
||||
step={0.001} // default to 3 decimal places
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
className={clsx(
|
||||
'bg-canvas-50 invalid:border-error invalid:text-error invalid:placeholder-rose-700 focus:outline-none focus:ring-1 disabled:cursor-not-allowed md:text-sm [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:m-0 [&::-webkit-outer-spin-button]:m-0',
|
||||
'w-full bg-canvas-50 invalid:border-error invalid:text-error invalid:placeholder-rose-700 focus:outline-none focus:ring-1 disabled:cursor-not-allowed md:text-sm [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:m-0 [&::-webkit-outer-spin-button]:m-0',
|
||||
error
|
||||
? 'border-error text-error focus:border-error focus:ring-error placeholder-rose-700' // matches invalid: styles
|
||||
: 'focus:border-canvas-200 focus:ring-transparent',
|
||||
!searchIcon && rowClassName,
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
/>
|
||||
@@ -33,9 +53,18 @@ export const Input = forwardRef(
|
||||
|
||||
if (searchIcon)
|
||||
return (
|
||||
<Row className={clsx(rowClassName)}>
|
||||
{searchIcon && <span className="search-icon">🔍</span>}
|
||||
<Row className={rowClassName}>
|
||||
<Search className="w-4 h-4 text-canvas-400" />
|
||||
{elem}
|
||||
{hasValue && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClear}
|
||||
className="text-canvas-400 hover:text-primary-600 transition-colors"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
)}
|
||||
</Row>
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user