Files
web/packages/design-system/lib/components/Select/Select.tsx
Matilda Haneling 6a008ba342 Merged in fix/book-149-incorrect-onfocus-behaviour-booking-widget (pull request #3320)
Fix/book 149 incorrect onfocus behaviour booking widget

* fix(BOOK-149): fixed labels shifting

* fix(BOOK-149): reintroduced sticky position

* fix(BOOK-149): added missing border to "where" text field

* added overflow to datepicker

* comment fixes

* removed separate typography declaration

* changed to onPress

* fix(BOOK-149): moved components to separate files

* fix(BOOK-149): removed desktop & mobile specific css classes

* fix(BOOK-149): new implementation of date and room modals

* dependencies update

* fix(BOOK-149): fixed child age dropdown issue, related error message, and Rooms & Guests container height

* updated info button to new variant

* fix(BOOK-149): prevent scrolling of background when modals are open in Tablet mode

* fixed overlay issue and added focus indicator on mobile

* fixed missing space in css

* rebase and fixed icon buttons after update

* simplified to use explicit boolean

* PR comments fixes

* more PR comment fixes

* PR comment fixes

* fixed setIsOpen((prev) => !prev)

* fixed issues with room error not showing properly on mobile

* fixing pr comments

* fixed flickering on GuestRoomModal


Approved-by: Erik Tiekstra
2026-01-12 14:18:51 +00:00

113 lines
2.7 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,
popoverWidth,
...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}
style={popoverWidth ? { minWidth: popoverWidth } : undefined}
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>
)
}