feat: (SW-3655) new Input and FormInput components * First version new Input and FormInput components * Handle aria-describedby with react-aria instead of manually add it * Update breaking unit and stories tests * Merge branch 'master' into feat/SW-3655-input-component * Update example form * Merge branch 'master' into feat/SW-3655-input-component * New lock file Approved-by: Linus Flood
108 lines
2.6 KiB
TypeScript
108 lines
2.6 KiB
TypeScript
import {
|
|
Select as AriaSelect,
|
|
SelectValue,
|
|
Popover,
|
|
ListBox,
|
|
Button,
|
|
} from 'react-aria-components'
|
|
import { cx } from 'class-variance-authority'
|
|
|
|
import { MaterialIcon } from '../Icons/MaterialIcon'
|
|
import { Typography } from '../Typography'
|
|
import { SelectItem } from './SelectItem'
|
|
import { SelectFilter } from './SelectFilter'
|
|
|
|
import type { SelectProps, SelectFilterProps } from './types'
|
|
|
|
import styles from './select.module.css'
|
|
import { useState } from 'react'
|
|
import { InputLabel } from '../InputLabel'
|
|
|
|
export function Select({
|
|
name,
|
|
label,
|
|
items,
|
|
isDisabled,
|
|
icon,
|
|
itemIcon,
|
|
...props
|
|
}: SelectProps | SelectFilterProps) {
|
|
const [isOpen, setIsOpen] = useState(false)
|
|
|
|
if (props.enableFiltering) {
|
|
return (
|
|
<SelectFilter
|
|
name={name}
|
|
label={label}
|
|
items={items}
|
|
icon={icon}
|
|
itemIcon={itemIcon}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
const iconColor = isDisabled ? 'Icon/Interactive/Disabled' : 'Icon/Default'
|
|
|
|
return (
|
|
<AriaSelect
|
|
className={styles.select}
|
|
name={name}
|
|
aria-label={label}
|
|
isDisabled={isDisabled}
|
|
onOpenChange={setIsOpen}
|
|
{...props}
|
|
>
|
|
<Button className={cx(styles.inner, styles.button)}>
|
|
{icon ? (
|
|
<MaterialIcon
|
|
icon={icon}
|
|
size={24}
|
|
color={iconColor}
|
|
aria-hidden="true"
|
|
/>
|
|
) : null}
|
|
<SelectValue className={cx(styles.displayText, styles.selectValue)}>
|
|
{({ selectedText }) => {
|
|
return (
|
|
<>
|
|
<InputLabel
|
|
className={styles.label}
|
|
selected={Boolean(selectedText || isOpen)}
|
|
>
|
|
{label}
|
|
</InputLabel>
|
|
<Typography variant="Body/Paragraph/mdRegular">
|
|
<span className={styles.selectedText}>{selectedText}</span>
|
|
</Typography>
|
|
</>
|
|
)
|
|
}}
|
|
</SelectValue>
|
|
|
|
<MaterialIcon
|
|
icon="chevron_right"
|
|
size={24}
|
|
color={iconColor}
|
|
aria-hidden="true"
|
|
className={styles.chevron}
|
|
/>
|
|
</Button>
|
|
|
|
<Popover className={styles.popover} shouldFlip={false}>
|
|
<ListBox className={styles.listBox}>
|
|
{items.map((item, idx) => (
|
|
<SelectItem
|
|
key={`${item.value}-${idx}`}
|
|
id={item.value}
|
|
icon={item.icon || itemIcon}
|
|
isDisabled={item.isDisabled}
|
|
>
|
|
{item.label}
|
|
</SelectItem>
|
|
))}
|
|
</ListBox>
|
|
</Popover>
|
|
</AriaSelect>
|
|
)
|
|
}
|