Skip to content

Commit

Permalink
Refactor data-select to popup attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
atomiks committed Oct 21, 2024
1 parent 7c827bf commit 3011201
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 47 deletions.
7 changes: 3 additions & 4 deletions docs/data/components/select/select.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Here is an example of how to apply a symmetric scale and fade transition with th
}

/* Represents the final styles once entered */
.SelectPopup[data-select='open'] {
.SelectPopup[data-open] {
opacity: 1;
transform: scale(1);
}
Expand Down Expand Up @@ -258,7 +258,7 @@ In newer browsers, there is a feature called `@starting-style` which allows tran

/* Official Browser API - no Firefox support as of May 2024 */
@starting-style {
.SelectPopup[data-select='open'] {
.SelectPopup[data-open] {
opacity: 0;
transform: scale(0.9);
}
Expand Down Expand Up @@ -330,8 +330,7 @@ function App() {

Four states are available as data attributes to animate the popup, which enables full control depending on whether the popup is being animated with CSS transitions or animations, JavaScript, or is using the `keepMounted` prop.

- `[data-select="open"]` - `open` state is `true`.
- `[data-select="closed"]` - `open` state is `false`. Can still be mounted to the DOM if closing.
- `[data-open]` - `open` state is `true`.
- `[data-entering]` - the popup was just inserted to the DOM. The attribute is removed 1 animation frame later. Enables "starting styles" upon insertion for conditional rendering.
- `[data-exiting]` - the popup is in the process of being removed from the DOM, but is still mounted.

Expand Down
4 changes: 2 additions & 2 deletions packages/mui-base/src/Select/Arrow/SelectArrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useForkRef } from '../../utils/useForkRef';
import { mergeReactProps } from '../../utils/mergeReactProps';
import type { BaseUIComponentProps } from '../../utils/types';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';

/**
*
Expand Down Expand Up @@ -58,7 +58,7 @@ const SelectArrow = React.forwardRef(function SelectArrow(
ownerState,
ref: mergedRef,
extraProps: otherProps,
customStyleHookMapping: commonStyleHooks,
customStyleHookMapping: popupOpenStateMapping,
});

if (alignOptionToTrigger) {
Expand Down
27 changes: 23 additions & 4 deletions packages/mui-base/src/Select/Backdrop/SelectBackdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,24 @@ import { HTMLElementType } from '../../utils/proptypes';
import { useForkRef } from '../../utils/useForkRef';
import { useSelectRootContext } from '../Root/SelectRootContext';
import { useSelectBackdrop } from './useSelectBackdrop';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';
import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps';
import type { TransitionStatus } from '../../utils/useTransitionStatus';

const customStyleHookMapping: CustomStyleHookMapping<SelectBackdrop.OwnerState> = commonStyleHooks;
const customStyleHookMapping: CustomStyleHookMapping<SelectBackdrop.OwnerState> = {
...popupOpenStateMapping,
transitionStatus(value): Record<string, string> | null {
if (value === 'entering') {
return { 'data-entering': '' };
}

if (value === 'exiting') {
return { 'data-exiting': '' };
}

return null;
},
};

/**
*
Expand All @@ -29,13 +43,16 @@ const SelectBackdrop = React.forwardRef(function SelectBackdrop(
) {
const { className, render, keepMounted = false, container, ...otherProps } = props;

const { open, mounted, backdropRef } = useSelectRootContext();
const { open, mounted, backdropRef, transitionStatus } = useSelectRootContext();

const { getBackdropProps } = useSelectBackdrop();

const mergedRef = useForkRef(backdropRef, forwardedRef);

const ownerState: SelectBackdrop.OwnerState = React.useMemo(() => ({ open }), [open]);
const ownerState: SelectBackdrop.OwnerState = React.useMemo(
() => ({ open, transitionStatus }),
[open, transitionStatus],
);

const { renderElement } = useComponentRenderer({
propGetter: getBackdropProps,
Expand Down Expand Up @@ -68,8 +85,10 @@ namespace SelectBackdrop {
*/
container?: HTMLElement | null | React.MutableRefObject<HTMLElement | null>;
}

export interface OwnerState {
open: boolean;
transitionStatus: TransitionStatus;
}
}

Expand Down
16 changes: 3 additions & 13 deletions packages/mui-base/src/Select/Group/SelectGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type { BaseUIComponentProps } from '../../utils/types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { mergeReactProps } from '../../utils/mergeReactProps';
import { SelectGroupContext } from './SelectGroupContext';
import { useSelectRootContext } from '../Root/SelectRootContext';

const ownerState = {};

/**
*
Expand All @@ -23,17 +24,8 @@ const SelectGroup = React.forwardRef(function SelectGroup(
) {
const { className, render, ...otherProps } = props;

const { open } = useSelectRootContext();

const [labelId, setLabelId] = React.useState<string | undefined>();

const ownerState: SelectGroup.OwnerState = React.useMemo(
() => ({
open,
}),
[open],
);

const getSelectOptionGroupProps = React.useCallback(
(externalProps = {}) =>
mergeReactProps(externalProps, {
Expand Down Expand Up @@ -68,9 +60,7 @@ const SelectGroup = React.forwardRef(function SelectGroup(
});

namespace SelectGroup {
export interface OwnerState {
open: boolean;
}
export interface OwnerState {}

export interface Props extends BaseUIComponentProps<'div', OwnerState> {}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/mui-base/src/Select/Icon/SelectIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import type { BaseUIComponentProps } from '../../utils/types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { mergeReactProps } from '../../utils/mergeReactProps';

/**
*
* Demos:
Expand Down Expand Up @@ -43,6 +44,7 @@ const SelectIcon = React.forwardRef(function SelectIcon(

namespace SelectIcon {
export interface OwnerState {}

export interface Props extends BaseUIComponentProps<'span', OwnerState> {}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/mui-base/src/Select/Option/SelectOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useId } from '../../utils/useId';
import { useForkRef } from '../../utils/useForkRef';
import { useEventCallback } from '../../utils/useEventCallback';
import { SelectOptionContext } from './SelectOptionContext';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';
import { useEnhancedEffect } from '../../utils/useEnhancedEffect';
import { useCompositeListItem } from '../../Composite/List/useCompositeListItem';

Expand Down Expand Up @@ -65,7 +65,7 @@ const InnerSelectOption = React.forwardRef(function InnerSelectOption(
return getItemProps(rootItemProps);
},
extraProps: otherProps,
customStyleHookMapping: commonStyleHooks,
customStyleHookMapping: popupOpenStateMapping,
});

return renderElement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import type { BaseUIComponentProps } from '../../utils/types';
import { useSelectRootContext } from '../Root/SelectRootContext';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps';
import { useSelectOptionContext } from '../Option/SelectOptionContext';
import { mergeReactProps } from '../../utils/mergeReactProps';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';

const customStyleHookMapping: CustomStyleHookMapping<SelectOptionIndicator.OwnerState> =
commonStyleHooks;
popupOpenStateMapping;

/**
*
Expand Down
26 changes: 15 additions & 11 deletions packages/mui-base/src/Select/Popup/SelectPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,25 @@ import type { Side } from '@floating-ui/react';
import type { BaseUIComponentProps } from '../../utils/types';
import { useSelectRootContext } from '../Root/SelectRootContext';
import { useSelectPositionerContext } from '../Positioner/SelectPositionerContext';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useForkRef } from '../../utils/useForkRef';
import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps';
import { useSelectPopup } from './useSelectPopup';
import type { TransitionStatus } from '../../utils/useTransitionStatus';

const customStyleHookMapping: CustomStyleHookMapping<SelectPopup.OwnerState> = {
...commonStyleHooks,
entering(value) {
return value ? { 'data-entering': '' } : null;
},
exiting(value) {
return value ? { 'data-exiting': '' } : null;
...popupOpenStateMapping,
transitionStatus(value): Record<string, string> | null {
if (value === 'entering') {
return { 'data-entering': '' };
}

if (value === 'exiting') {
return { 'data-exiting': '' };
}

return null;
},
};

Expand Down Expand Up @@ -45,8 +51,7 @@ const SelectPopup = React.forwardRef(function SelectPopup(

const ownerState: SelectPopup.OwnerState = React.useMemo(
() => ({
entering: transitionStatus === 'entering',
exiting: transitionStatus === 'exiting',
transitionStatus,
side,
alignment,
open,
Expand Down Expand Up @@ -77,11 +82,10 @@ namespace SelectPopup {
}

export interface OwnerState {
entering: boolean;
exiting: boolean;
side: Side | 'none';
alignment: 'start' | 'end' | 'center';
open: boolean;
transitionStatus: TransitionStatus;
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/mui-base/src/Select/Positioner/SelectPositioner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { FloatingFocusManager, FloatingPortal, inner, type Side } from '@floatin
import type { BaseUIComponentProps } from '../../utils/types';
import { SelectPositionerContext } from './SelectPositionerContext';
import { useSelectRootContext } from '../Root/SelectRootContext';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useForkRef } from '../../utils/useForkRef';
import { useSelectPositioner } from './useSelectPositioner';
Expand All @@ -18,6 +17,7 @@ import { useLatestRef } from '../../utils/useLatestRef';
import { CompositeList } from '../../Composite/List/CompositeList';
import { useField } from '../../Field/useField';
import { useFieldControlValidation } from '../../Field/Control/useFieldControlValidation';
import { popupOpenStateMapping } from '../../utils/popupOpenStateMapping';

/**
* Renders the element that positions the Select popup.
Expand Down Expand Up @@ -207,7 +207,7 @@ const SelectPositioner = React.forwardRef(function SelectPositioner(
render: render ?? 'div',
className,
ownerState,
customStyleHookMapping: commonStyleHooks,
customStyleHookMapping: popupOpenStateMapping,
ref: mergedRef,
extraProps: otherProps,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/mui-base/src/Select/Trigger/SelectTrigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { useSelectTrigger } from './useSelectTrigger';
import { useSelectRootContext } from '../Root/SelectRootContext';
import { commonStyleHooks } from '../utils/commonStyleHooks';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { BaseUIComponentProps } from '../../utils/types';
import { useFieldRootContext } from '../../Field/Root/FieldRootContext';
import { triggerOpenStateMapping } from '../../utils/popupOpenStateMapping';

/**
*
Expand Down Expand Up @@ -59,7 +59,7 @@ const SelectTrigger = React.forwardRef(function SelectTrigger(
className,
ownerState,
propGetter: (externalProps) => getTriggerProps(getRootTriggerProps(externalProps)),
customStyleHookMapping: commonStyleHooks,
customStyleHookMapping: triggerOpenStateMapping,
extraProps: otherProps,
});

Expand Down
5 changes: 0 additions & 5 deletions packages/mui-base/src/Select/utils/commonStyleHooks.ts

This file was deleted.

0 comments on commit 3011201

Please sign in to comment.