fix: update design for select component and remove placeholders
This commit is contained in:
@@ -62,7 +62,6 @@ export default function FormContent() {
|
|||||||
items={languageSelect}
|
items={languageSelect}
|
||||||
label={intl.formatMessage({ id: "Language" })}
|
label={intl.formatMessage({ id: "Language" })}
|
||||||
name="language"
|
name="language"
|
||||||
placeholder={intl.formatMessage({ id: "Select language" })}
|
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<Divider className={styles.divider} color="subtle" />
|
<Divider className={styles.divider} color="subtle" />
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ const ageList = [...Array(13)].map((_, i) => ({
|
|||||||
value: i,
|
value: i,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const childDefaultValues = { age: -1, bed: -1 }
|
||||||
|
|
||||||
export default function ChildInfoSelector({
|
export default function ChildInfoSelector({
|
||||||
child = { age: -1, bed: -1 },
|
child,
|
||||||
childrenInAdultsBed,
|
childrenInAdultsBed,
|
||||||
adults,
|
adults,
|
||||||
index = 0,
|
index = 0,
|
||||||
@@ -89,11 +91,10 @@ export default function ChildInfoSelector({
|
|||||||
items={ageList}
|
items={ageList}
|
||||||
label={ageLabel}
|
label={ageLabel}
|
||||||
aria-label={ageLabel}
|
aria-label={ageLabel}
|
||||||
value={child.age}
|
value={child.age ?? childDefaultValues.age}
|
||||||
onSelect={(key) => {
|
onSelect={(key) => {
|
||||||
updateSelectedAge(key as number)
|
updateSelectedAge(key as number)
|
||||||
}}
|
}}
|
||||||
placeholder={ageLabel}
|
|
||||||
maxHeight={180}
|
maxHeight={180}
|
||||||
name={ageFieldName}
|
name={ageFieldName}
|
||||||
isNestedInModal={true}
|
isNestedInModal={true}
|
||||||
@@ -105,11 +106,10 @@ export default function ChildInfoSelector({
|
|||||||
items={getAvailableBeds(child.age)}
|
items={getAvailableBeds(child.age)}
|
||||||
label={bedLabel}
|
label={bedLabel}
|
||||||
aria-label={bedLabel}
|
aria-label={bedLabel}
|
||||||
value={child.bed}
|
value={child.bed ?? childDefaultValues.bed}
|
||||||
onSelect={(key) => {
|
onSelect={(key) => {
|
||||||
updateSelectedBed(key as number)
|
updateSelectedBed(key as number)
|
||||||
}}
|
}}
|
||||||
placeholder={bedLabel}
|
|
||||||
name={bedFieldName}
|
name={bedFieldName}
|
||||||
isNestedInModal={true}
|
isNestedInModal={true}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -138,7 +138,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
|
|||||||
onSelect={(key: Key) =>
|
onSelect={(key: Key) =>
|
||||||
setValue(DateName.day, Number(key))
|
setValue(DateName.day, Number(key))
|
||||||
}
|
}
|
||||||
placeholder={dayLabel}
|
|
||||||
required
|
required
|
||||||
tabIndex={3}
|
tabIndex={3}
|
||||||
value={segment.isPlaceholder ? undefined : segment.value}
|
value={segment.isPlaceholder ? undefined : segment.value}
|
||||||
@@ -158,7 +157,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
|
|||||||
onSelect={(key: Key) =>
|
onSelect={(key: Key) =>
|
||||||
setValue(DateName.month, Number(key))
|
setValue(DateName.month, Number(key))
|
||||||
}
|
}
|
||||||
placeholder={monthLabel}
|
|
||||||
required
|
required
|
||||||
tabIndex={2}
|
tabIndex={2}
|
||||||
value={segment.isPlaceholder ? undefined : segment.value}
|
value={segment.isPlaceholder ? undefined : segment.value}
|
||||||
@@ -178,7 +176,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
|
|||||||
onSelect={(key: Key) =>
|
onSelect={(key: Key) =>
|
||||||
setValue(DateName.year, Number(key))
|
setValue(DateName.year, Number(key))
|
||||||
}
|
}
|
||||||
placeholder={yearLabel}
|
|
||||||
required
|
required
|
||||||
tabIndex={1}
|
tabIndex={1}
|
||||||
value={segment.isPlaceholder ? undefined : segment.value}
|
value={segment.isPlaceholder ? undefined : segment.value}
|
||||||
|
|||||||
@@ -37,6 +37,11 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.container:has(.input:not(:placeholder-shown)) {
|
||||||
|
align-content: space-around;
|
||||||
|
gap: var(--Spacing-x-half);
|
||||||
|
}
|
||||||
|
|
||||||
.input:not(:active, :focus):placeholder-shown {
|
.input:not(:active, :focus):placeholder-shown {
|
||||||
height: 0px;
|
height: 0px;
|
||||||
transition: height 150ms ease;
|
transition: height 150ms ease;
|
||||||
|
|||||||
@@ -24,48 +24,47 @@ span.discreet {
|
|||||||
order: unset;
|
order: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle input and textarea fields */
|
||||||
input:active ~ .label,
|
input:active ~ .label,
|
||||||
input:not(:placeholder-shown) ~ .label {
|
input:not(:placeholder-shown) ~ .label,
|
||||||
display: block;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:focus ~ .label {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:placeholder-shown ~ .label {
|
|
||||||
grid-row: 1/-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:placeholder-shown:focus ~ .label,
|
|
||||||
input:placeholder-shown:active ~ .label {
|
|
||||||
margin-bottom: var(--Spacing-x-half);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:disabled ~ .label {
|
|
||||||
color: var(--Main-Grey-40);
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea:active ~ .label,
|
textarea:active ~ .label,
|
||||||
textarea:not(:placeholder-shown) ~ .label {
|
textarea:not(:placeholder-shown) ~ .label {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input:focus ~ .label,
|
||||||
textarea:focus ~ .label {
|
textarea:focus ~ .label {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input:placeholder-shown ~ .label,
|
||||||
textarea:placeholder-shown ~ .label {
|
textarea:placeholder-shown ~ .label {
|
||||||
grid-row: 1/-1;
|
grid-row: 1/-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea:placeholder-shown:focus ~ .label,
|
input:placeholder-shown:focus ~ .label,
|
||||||
|
input:placeholder-shown:active ~ .label,
|
||||||
|
textarea:placeholder-shown.label,
|
||||||
textarea:placeholder-shown:active ~ .label {
|
textarea:placeholder-shown:active ~ .label {
|
||||||
margin-bottom: var(--Spacing-x-half);
|
margin-bottom: var(--Spacing-x-half);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea:disabled ~ .label {
|
input:disabled ~ .label,
|
||||||
|
textarea:disabled ~ .label,
|
||||||
|
:global(.select-container)[data-disabled] .label {
|
||||||
color: var(--Main-Grey-40);
|
color: var(--Main-Grey-40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle select fields */
|
||||||
|
:global(.select-button) .label {
|
||||||
|
order: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.select-container)[data-open="true"] .label:not(.discreet),
|
||||||
|
:global(.react-aria-SelectValue):has(:nth-child(2)) .label:not(.discreet),
|
||||||
|
:global(.select-button):active .label:not(.discreet) {
|
||||||
|
display: grid;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-bottom: var(--Spacing-x-half);
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ export default function Select({
|
|||||||
className,
|
className,
|
||||||
items,
|
items,
|
||||||
label,
|
label,
|
||||||
|
disabled,
|
||||||
name,
|
name,
|
||||||
placeholder,
|
|
||||||
registerOptions = {},
|
registerOptions = {},
|
||||||
}: SelectProps) {
|
}: SelectProps) {
|
||||||
const { control } = useFormContext()
|
const { control } = useFormContext()
|
||||||
@@ -24,14 +24,13 @@ export default function Select({
|
|||||||
<ReactAriaSelect
|
<ReactAriaSelect
|
||||||
className={className}
|
className={className}
|
||||||
defaultSelectedKey={field.value}
|
defaultSelectedKey={field.value}
|
||||||
disabled={field.disabled}
|
disabled={disabled || field.disabled}
|
||||||
items={items}
|
items={items}
|
||||||
label={label}
|
label={label}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
name={field.name}
|
name={field.name}
|
||||||
onBlur={field.onBlur}
|
onBlur={field.onBlur}
|
||||||
onSelect={field.onChange}
|
onSelect={field.onChange}
|
||||||
placeholder={placeholder}
|
|
||||||
value={field.value}
|
value={field.value}
|
||||||
data-testid={name}
|
data-testid={name}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { SelectProps as ReactAriaSelectProps } from "@/components/TempDesig
|
|||||||
export interface SelectProps
|
export interface SelectProps
|
||||||
extends Omit<
|
extends Omit<
|
||||||
React.SelectHTMLAttributes<HTMLSelectElement>,
|
React.SelectHTMLAttributes<HTMLSelectElement>,
|
||||||
"name" | "onSelect"
|
"name" | "onSelect" | "placeholder"
|
||||||
>,
|
>,
|
||||||
Omit<ReactAriaSelectProps, "onSelect" | "ref" | "value"> {
|
Omit<ReactAriaSelectProps, "onSelect" | "ref" | "value"> {
|
||||||
registerOptions?: RegisterOptions
|
registerOptions?: RegisterOptions
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export default function Select({
|
|||||||
label,
|
label,
|
||||||
name,
|
name,
|
||||||
onSelect,
|
onSelect,
|
||||||
placeholder,
|
disabled,
|
||||||
required = false,
|
required = false,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
value,
|
value,
|
||||||
@@ -54,45 +54,46 @@ export default function Select({
|
|||||||
onSelect(key)
|
onSelect(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let chevronProps = {}
|
||||||
|
|
||||||
|
if (discreet) {
|
||||||
|
chevronProps = { color: "baseButtonTextOnFillNormal" }
|
||||||
|
} else if (disabled) {
|
||||||
|
chevronProps = { color: "disabled" }
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.container} ${className}`} ref={setRef}>
|
<div className={`${styles.container} ${className}`} ref={setRef}>
|
||||||
<ReactAriaSelect
|
<ReactAriaSelect
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
className={`${styles.select} ${discreet && styles.discreet}`}
|
className={`${styles.select} ${discreet ? styles.discreet : ""} select-container`}
|
||||||
defaultSelectedKey={defaultSelectedKey}
|
defaultSelectedKey={defaultSelectedKey}
|
||||||
name={name}
|
name={name}
|
||||||
onSelectionChange={handleOnSelect}
|
onSelectionChange={handleOnSelect}
|
||||||
placeholder={placeholder}
|
|
||||||
selectedKey={value as Key}
|
selectedKey={value as Key}
|
||||||
onOpenChange={setOverflowVisible}
|
onOpenChange={setOverflowVisible}
|
||||||
|
isDisabled={disabled}
|
||||||
>
|
>
|
||||||
<Body asChild fontOnly>
|
<Body asChild fontOnly>
|
||||||
<Button className={styles.input} data-testid={name}>
|
<Button
|
||||||
<span className={styles.inputContentWrapper} tabIndex={tabIndex}>
|
className={`${styles.input} select-button`}
|
||||||
<SelectValue>
|
data-testid={name}
|
||||||
{({ isPlaceholder, selectedText }) => (
|
>
|
||||||
<>
|
<SelectValue tabIndex={tabIndex}>
|
||||||
<Label
|
{({ selectedText }) => (
|
||||||
required={required}
|
<>
|
||||||
size={discreet ? "discreet" : "small"}
|
<Label
|
||||||
>
|
required={required}
|
||||||
{label}
|
size={discreet ? "discreet" : "regular"}
|
||||||
{discreet && `:`}
|
>
|
||||||
</Label>
|
{label}
|
||||||
{isPlaceholder ? (
|
{discreet && `:`}
|
||||||
placeholder ? (
|
</Label>
|
||||||
<Body color="uiTextPlaceholder"> {placeholder}</Body>
|
{selectedText && <Body>{selectedText}</Body>}
|
||||||
) : null
|
</>
|
||||||
) : (
|
)}
|
||||||
selectedText
|
</SelectValue>
|
||||||
)}
|
<SelectChevron {...chevronProps} />
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</SelectValue>
|
|
||||||
</span>
|
|
||||||
<SelectChevron
|
|
||||||
{...(discreet ? { color: "baseButtonTextOnFillNormal" } : {})}
|
|
||||||
/>
|
|
||||||
</Button>
|
</Button>
|
||||||
</Body>
|
</Body>
|
||||||
<Body asChild fontOnly>
|
<Body asChild fontOnly>
|
||||||
|
|||||||
@@ -33,11 +33,11 @@
|
|||||||
gap: var(--Spacing-x1);
|
gap: var(--Spacing-x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.select.discreet .inputContentWrapper {
|
.select[data-disabled],
|
||||||
align-items: center;
|
.select[data-disabled] .input {
|
||||||
justify-content: flex-end;
|
background-color: var(--UI-Input-Controls-Surface-Disabled);
|
||||||
flex-direction: row;
|
border: none;
|
||||||
font-weight: 500;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
@@ -54,14 +54,21 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputContentWrapper {
|
.input :global(.react-aria-SelectValue) {
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--Spacing-x-half);
|
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select.discreet :global(.react-aria-SelectValue) {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
flex-direction: row;
|
||||||
|
font-weight: 500;
|
||||||
|
gap: var(--Spacing-x-half);
|
||||||
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
background-color: var(--Main-Grey-White);
|
background-color: var(--Main-Grey-White);
|
||||||
border-radius: var(--Corner-radius-Medium);
|
border-radius: var(--Corner-radius-Medium);
|
||||||
@@ -110,3 +117,20 @@
|
|||||||
.listBoxItem[data-selected="true"].showRadioButton:before {
|
.listBoxItem[data-selected="true"].showRadioButton:before {
|
||||||
box-shadow: inset 0 0 0 8px var(--UI-Input-Controls-Fill-Selected);
|
box-shadow: inset 0 0 0 8px var(--UI-Input-Controls-Fill-Selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use global react aria classnames here since setting a css modules classname overrides
|
||||||
|
the class set by react aria.We use that class to style the child label component. */
|
||||||
|
.select:not(.discreet) :global(.react-aria-SelectValue) {
|
||||||
|
display: grid;
|
||||||
|
transition: height 200ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input :global(.react-aria-SelectValue) {
|
||||||
|
height: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input :global(.react-aria-SelectValue):has(:nth-child(2)) {
|
||||||
|
height: 38px;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ export interface SelectProps
|
|||||||
label: string
|
label: string
|
||||||
name: string
|
name: string
|
||||||
onSelect: (key: Key) => void
|
onSelect: (key: Key) => void
|
||||||
placeholder?: string
|
|
||||||
value?: string | number
|
value?: string | number
|
||||||
maxHeight?: number
|
maxHeight?: number
|
||||||
showRadioButton?: boolean
|
showRadioButton?: boolean
|
||||||
|
|||||||
Reference in New Issue
Block a user