Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions packages/react/src/Autocomplete/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TextInput from '../TextInput'
import {useMergedRefs} from '../hooks/useMergedRefs'
import type {ComponentProps} from '../utils/types'
import useSafeTimeout from '../hooks/useSafeTimeout'
import {mergeProps} from '../utils/mergeProps'

type InternalAutocompleteInputProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -170,22 +171,26 @@ const AutocompleteInput = React.forwardRef(

return (
<Component
onFocus={handleInputFocus}
onBlur={handleInputBlur}
onChange={handleInputChange}
onKeyDown={handleInputKeyDown}
onKeyPress={onInputKeyPress}
onKeyUp={handleInputKeyUp}
ref={mergedRef}
aria-controls={`${id}-listbox`}
aria-autocomplete="both"
role="combobox"
aria-expanded={showMenu}
aria-haspopup="listbox"
aria-owns={`${id}-listbox`}
autoComplete="off"
id={id}
{...props}
{...mergeProps(
{
onFocus: handleInputFocus,
onBlur: handleInputBlur,
onChange: handleInputChange,
onKeyDown: handleInputKeyDown,
onKeyPress: onInputKeyPress,
onKeyUp: handleInputKeyUp,
'aria-controls': `${id}-listbox`,
'aria-autocomplete': 'both' as const,
role: 'combobox',
'aria-expanded': showMenu,
'aria-haspopup': 'listbox',
'aria-owns': `${id}-listbox`,
autoComplete: 'off',
id,
},
props,
)}
data-component="Autocomplete.Input"
/>
)
Expand Down
33 changes: 25 additions & 8 deletions packages/react/src/Autocomplete/AutocompleteOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import VisuallyHidden from '../_VisuallyHidden'

import classes from './AutocompleteOverlay.module.css'
import {clsx} from 'clsx'
import {mergeProps} from '../utils/mergeProps'

type AutocompleteOverlayInternalProps = {
/**
Expand All @@ -36,6 +37,12 @@ function AutocompleteOverlay({
throw new Error('AutocompleteContext returned null values')
}
const overlayProps = {...oldOverlayProps, ...newOverlayProps}
const {
className: overlayClassName,
onClickOutside: consumerOnClickOutside,
onEscape: consumerOnEscape,
...overlayRest
} = overlayProps
const {inputRef, scrollContainerRef, selectedItemLength, setShowMenu, showMenu = false} = autocompleteContext

const computedAnchorRef = useRef<HTMLElement | null>(null)
Expand All @@ -62,22 +69,32 @@ function AutocompleteOverlay({
const closeOptionList = useCallback(() => {
setShowMenu(false)
}, [setShowMenu])
const onClickOutside = consumerOnClickOutside
? mergeProps({onClickOutside: closeOptionList}, {onClickOutside: consumerOnClickOutside}).onClickOutside
: closeOptionList
const onEscape = consumerOnEscape
? mergeProps({onEscape: closeOptionList}, {onEscape: consumerOnEscape}).onEscape
: closeOptionList

if (typeof window === 'undefined') {
return null
}

return showMenu ? (
<Overlay
returnFocusRef={inputRef}
preventFocusOnOpen={true}
onClickOutside={closeOptionList}
onEscape={closeOptionList}
ref={mergedScrollContainerRef}
top={position?.top}
left={position?.left}
className={clsx(classes.Overlay, className)}
{...overlayProps}
returnFocusRef={inputRef}
{...mergeProps(
{
preventFocusOnOpen: true,
onClickOutside,
onEscape,
top: position?.top,
left: position?.left,
className: clsx(classes.Overlay, className, overlayClassName),
},
overlayRest,
)}
data-component="Autocomplete.Overlay"
>
{children}
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/Checkbox/Checkbox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ describe('Checkbox', () => {
expect(checkbox.checked).toEqual(false)

await user.click(checkbox)
expect(handleChange).toHaveBeenCalled()
expect(handleChange).toHaveBeenCalledTimes(1)
expect(checkbox.checked).toEqual(true)

await user.click(checkbox)
expect(handleChange).toHaveBeenCalled()
expect(handleChange).toHaveBeenCalledTimes(2)
expect(checkbox.checked).toEqual(false)
})

Expand Down
8 changes: 4 additions & 4 deletions packages/react/src/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {CheckboxGroupContext} from '../CheckboxGroup/CheckboxGroupContext'
import classes from './Checkbox.module.css'
import sharedClasses from './shared.module.css'
import type {WithSlotMarker} from '../utils/types'
import {mergeProps} from '../utils/mergeProps'

export type CheckboxProps = {
/**
Expand Down Expand Up @@ -87,7 +88,6 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
const inputProps = {
type: 'checkbox',
disabled,
ref: appliedRef,
checked: indeterminate ? false : checked,
defaultChecked,
required,
Expand All @@ -96,7 +96,6 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
onChange: handleOnChange,
value,
name: value,
...rest,
}

useLayoutEffect(() => {
Expand All @@ -118,9 +117,10 @@ const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
}
})
return (
// @ts-expect-error inputProp needs a non nullable ref
<input
{...inputProps}
// @ts-expect-error input requires a non-nullable ref
ref={appliedRef}
{...mergeProps(inputProps, rest)}
data-component={dataComponent ?? 'Checkbox'}
className={clsx(className, sharedClasses.Input, classes.Checkbox)}
/>
Expand Down
35 changes: 21 additions & 14 deletions packages/react/src/DataTable/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {ScrollableRegion} from '../ScrollableRegion'
import {Button} from '../internal/components/ButtonReset'
import classes from './Table.module.css'
import type {PolymorphicProps} from '../utils/modern-polymorphic'
import {mergeProps} from '../utils/mergeProps'

// ----------------------------------------------------------------------------
// Table
Expand Down Expand Up @@ -52,12 +53,11 @@ const Table = React.forwardRef<HTMLTableElement, TableProps>(function Table(
className={clsx('TableOverflowWrapper', classes.TableOverflowWrapper)}
>
<table
{...rest}
ref={ref}
{...mergeProps({className: clsx(className, 'Table', classes.Table)}, rest)}
aria-labelledby={labelledby}
data-cell-padding={cellPadding}
className={clsx(className, 'Table', classes.Table)}
role="table"
ref={ref}
style={{'--grid-template-columns': gridTemplateColumns} as React.CSSProperties}
data-component="Table"
/>
Expand Down Expand Up @@ -108,12 +108,13 @@ export type TableHeaderProps = Omit<React.ComponentPropsWithoutRef<'th'>, 'align
align?: CellAlignment
}

function TableHeader({align, children, ...rest}: TableHeaderProps) {
function TableHeader({align, children, className, ...rest}: TableHeaderProps) {
return (
<th
data-component="Table.Header"
{...rest}
className={clsx('TableHeader', classes.TableHeader)}
{...mergeProps(
{'data-component': 'Table.Header', className: clsx('TableHeader', classes.TableHeader, className)},
rest,
)}
role="columnheader"
scope="col"
data-cell-align={align}
Expand All @@ -140,7 +141,7 @@ function TableSortHeader({align, children, direction, onToggleSort, ...rest}: Ta
const ariaSort = direction === 'DESC' ? 'descending' : direction === 'ASC' ? 'ascending' : undefined

return (
<TableHeader {...rest} aria-sort={ariaSort} align={align} data-component="Table.SortHeader">
<TableHeader {...mergeProps({}, rest)} aria-sort={ariaSort} align={align} data-component="Table.SortHeader">
<Button
type="button"
className={clsx('TableSortButton', classes.TableSortButton)}
Expand Down Expand Up @@ -184,9 +185,13 @@ function TableSortHeader({align, children, direction, onToggleSort, ...rest}: Ta

export type TableRowProps = React.ComponentPropsWithoutRef<'tr'>

function TableRow({children, ...rest}: TableRowProps) {
function TableRow({children, className, ...rest}: TableRowProps) {
return (
<tr {...rest} className={clsx('TableRow', classes.TableRow)} role="row" data-component="Table.Row">
<tr
{...mergeProps({className: clsx('TableRow', classes.TableRow, className)}, rest)}
role="row"
data-component="Table.Row"
>
{children}
</tr>
)
Expand Down Expand Up @@ -215,8 +220,7 @@ function TableCell({align, className, children, scope, ...rest}: TableCellProps)

return (
<BaseComponent
{...rest}
className={clsx('TableCell', className, classes.TableCell)}
{...mergeProps({className: clsx('TableCell', className, classes.TableCell)}, rest)}
scope={scope}
role={role}
data-cell-align={align}
Expand Down Expand Up @@ -251,7 +255,10 @@ function TableContainer<As extends React.ElementType = 'div'>({
}: TableContainerProps<As>) {
const Component = as || 'div'
return (
<Component {...rest} className={clsx(className, classes.TableContainer)} data-component="Table.Container">
<Component
{...mergeProps({className: clsx(className, classes.TableContainer)}, rest)}
data-component="Table.Container"
>
{children}
</Component>
)
Expand Down Expand Up @@ -354,7 +361,7 @@ export type TableSkeletonProps<Data extends UniqueRow> = React.ComponentPropsWit
function TableSkeleton<Data extends UniqueRow>({cellPadding, columns, rows = 10, ...rest}: TableSkeletonProps<Data>) {
const {gridTemplateColumns} = useTableLayout(columns)
return (
<Table {...rest} cellPadding={cellPadding} gridTemplateColumns={gridTemplateColumns}>
<Table {...mergeProps({cellPadding, gridTemplateColumns}, rest)}>
<TableHead>
<TableRow>
{Array.isArray(columns)
Expand Down
9 changes: 6 additions & 3 deletions packages/react/src/Details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {warning} from '../utils/warning'
import {clsx} from 'clsx'
import classes from './Details.module.css'
import {useMergedRefs} from '../hooks/useMergedRefs'
import {mergeProps} from '../utils/mergeProps'

const Root = React.forwardRef<HTMLDetailsElement, DetailsProps>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -28,9 +29,8 @@ const Root = React.forwardRef<HTMLDetailsElement, DetailsProps>(

return (
<details
className={clsx(className, classes.Details)}
{...rest}
ref={ref}
{...mergeProps({className: clsx(className, classes.Details)}, rest)}
data-component={dataComponent ?? 'Details'}
>
{children}
Expand All @@ -52,7 +52,10 @@ export type SummaryProps<As extends React.ElementType> = {
function Summary<As extends React.ElementType>({as, children, ...props}: SummaryProps<As>) {
const Component = as ?? 'summary'
return (
<Component as={Component === 'summary' ? null : 'summary'} {...props} data-component="Details.Summary">
<Component
{...mergeProps({as: Component === 'summary' ? null : 'summary'}, props)}
data-component="Details.Summary"
>
{children}
</Component>
)
Expand Down
22 changes: 14 additions & 8 deletions packages/react/src/FilteredActionList/FilteredActionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {useVirtualizer} from '@tanstack/react-virtual'
import {useMergedRefs, useProvidedRefOrCreate} from '../hooks'
import {useFeatureFlag} from '../FeatureFlags'
import {FilteredActionListInput} from './FilteredActionListInput'
import {mergeProps} from '../utils/mergeProps'

const menuScrollMargins: ScrollIntoViewOptions = {startMargin: 0, endMargin: 8}

Expand Down Expand Up @@ -631,21 +632,26 @@ const MappedActionListItem = forwardRef<HTMLLIElement, ItemInput & {renderItem?:
trailingText,
trailingIcon: TrailingIcon,
onAction,
className,
children,
...rest
} = item

return (
<ActionList.Item
role="option"
// @ts-ignore - for now
onSelect={(e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => {
if (typeof onAction === 'function')
onAction(item, e as React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>)
}}
data-id={id}
ref={ref}
{...rest}
{...(mergeProps(
{
role: 'option',
onSelect: (e: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => {
if (typeof onAction === 'function')
onAction(item, e as React.MouseEvent<HTMLDivElement> | React.KeyboardEvent<HTMLDivElement>)
},
'data-id': id,
className,
},
rest,
) as React.ComponentProps<typeof ActionList.Item>)}
>
{LeadingVisual ? (
<ActionList.LeadingVisual>
Expand Down
Loading
Loading