Skip to content

Commit 20fb542

Browse files
committed
refactor(Collapsible): split context files and update transition status hook
1 parent e97cfcc commit 20fb542

File tree

8 files changed

+50
-59
lines changed

8 files changed

+50
-59
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { createSafeContext } from "../../primitives";
2+
3+
export type CollapsibleContentContextValue = {
4+
id: string;
5+
open: boolean;
6+
duration: number;
7+
};
8+
9+
export const [CollapsibleContentContext, useCollapsibleContent] = createSafeContext<CollapsibleContentContextValue>({
10+
name: "CollapsibleContentContext",
11+
});

packages/react-ui/src/components/collapsible/collapsible-content.tsx

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1-
import { type CSSProperties, useEffect, useRef, useState } from "react";
2-
import { useIsomorphicEffect, useMergeRefs } from "../../hooks";
1+
import { type CSSProperties, useEffect, useState } from "react";
2+
import { useElementTransitionStatus, useIsomorphicEffect, useMergeRefs } from "../../hooks";
33
import type { EmptyObject, PrimitiveProps } from "../../primitives";
44
import { useOrientation } from "../../primitives/composite/orientation-context";
55
import { tx } from "../../utils";
6-
import { useCollapsibleContent } from "./collapsible-context";
6+
import { useCollapsibleContent } from "./collapsible-content-context";
77

88
export const CollapsibleContent = (props: PrimitiveProps<"div", EmptyObject, "id">) => {
99
const { children, ref, ...rest } = props;
1010

11-
const { id, open, mounted, status, setElement } = useCollapsibleContent();
12-
1311
const orientation = useOrientation(true);
1412

15-
const elemRef = useRef<HTMLDivElement>(null);
13+
const { id, open, duration } = useCollapsibleContent();
14+
15+
const { isMounted, status, element, setElement } = useElementTransitionStatus(open, { duration });
16+
1617
const [size, setSize] = useState<{ width?: number; height?: number }>();
1718

18-
const [skipAnimation, setSkipAnimation] = useState(open || mounted);
19+
const [skipAnimation, setSkipAnimation] = useState(open || isMounted);
1920

2021
useEffect(() => {
2122
const raf = requestAnimationFrame(() => {
@@ -28,19 +29,19 @@ export const CollapsibleContent = (props: PrimitiveProps<"div", EmptyObject, "id
2829
}, []);
2930

3031
useIsomorphicEffect(() => {
31-
if (mounted && elemRef.current) {
32-
const rect = elemRef.current.getBoundingClientRect();
32+
if (isMounted && element) {
33+
const rect = element.getBoundingClientRect();
3334

3435
setSize({
3536
width: rect.width,
3637
height: rect.height,
3738
});
3839
}
39-
}, [mounted]);
40+
}, [element, isMounted]);
4041

41-
const refs = useMergeRefs(ref, elemRef, setElement);
42+
const refs = useMergeRefs(ref, setElement);
4243

43-
if (!mounted) {
44+
if (!isMounted) {
4445
return null;
4546
}
4647

packages/react-ui/src/components/collapsible/collapsible-context.ts

-25
This file was deleted.

packages/react-ui/src/components/collapsible/collapsible-root.tsx

+5-13
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
import { type CSSProperties, useId } from "react";
2-
import { useDisclosure, useElementTransitionStatus } from "../../hooks";
2+
import { useDisclosure } from "../../hooks";
33
import type { PrimitiveProps } from "../../primitives";
44
import type { DisclosureProps } from "../../shared/types";
55
import { tx } from "../../utils";
6-
import {
7-
CollapsibleContentContext,
8-
type CollapsibleContentContextValue,
9-
CollapsibleTriggerContext,
10-
type CollapsibleTriggerContextValue,
11-
} from "./collapsible-context";
6+
import { CollapsibleContentContext, type CollapsibleContentContextValue } from "./collapsible-content-context";
7+
import { CollapsibleTriggerContext, type CollapsibleTriggerContextValue } from "./collapsible-trigger-context";
128

139
export type CollapsibleRootProps = DisclosureProps & {
1410
/**
@@ -35,21 +31,17 @@ export const CollapsibleRoot = (props: PrimitiveProps<"div", CollapsibleRootProp
3531

3632
const id = useId();
3733

38-
const { isMounted, status, setElement } = useElementTransitionStatus(openState, { duration });
39-
4034
const triggerContext: CollapsibleTriggerContextValue = {
4135
id,
36+
disabled,
4237
open: openState,
4338
toggle: handleToggle,
44-
disabled,
4539
};
40+
4641
const contentContext: CollapsibleContentContextValue = {
4742
id,
4843
open: openState,
49-
mounted: isMounted,
50-
status,
5144
duration,
52-
setElement,
5345
};
5446

5547
return (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { createSafeContext } from "../../primitives";
2+
3+
export type CollapsibleTriggerContextValue = {
4+
id: string;
5+
disabled: boolean;
6+
open: boolean;
7+
toggle: () => void;
8+
};
9+
10+
export const [CollapsibleTriggerContext, useCollapsibleTrigger] = createSafeContext<CollapsibleTriggerContextValue>({
11+
name: "CollapsibleTriggerContext",
12+
});

packages/react-ui/src/components/collapsible/collapsible-trigger.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { MouseEvent } from "react";
22
import { useButtonProps } from "../../hooks";
33
import { type EmptyObject, Polymorphic, type PolymorphicProps } from "../../primitives";
4-
import { useCollapsibleTrigger } from "./collapsible-context";
4+
import { useCollapsibleTrigger } from "./collapsible-trigger-context";
55

66
export const CollapsibleTrigger = (props: PolymorphicProps<"button", EmptyObject, "type" | "disabled">) => {
77
const { render, tabIndex, children, onClick, ...rest } = props;
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,19 @@
11
import { type FloatingContext, useTransitionStatus, type UseTransitionStatusProps } from "@floating-ui/react";
2-
import { useCallback, useState } from "react";
2+
import { useState } from "react";
33

44
export const useElementTransitionStatus = <E extends HTMLElement = HTMLElement>(
55
open: boolean,
66
props?: UseTransitionStatusProps,
77
) => {
8-
const [elementState, setElementState] = useState<E | null>(null);
9-
10-
const setElement = useCallback((node: E | null) => {
11-
setElementState(node);
12-
}, []);
8+
const [element, setElement] = useState<E | null>(null);
139

1410
const { isMounted, status } = useTransitionStatus(
1511
{
1612
open,
17-
elements: { floating: elementState, reference: null, domReference: null },
13+
elements: { floating: element, reference: null, domReference: null },
1814
} as unknown as FloatingContext,
1915
props,
2016
);
2117

22-
return { isMounted, status, setElement };
18+
return { isMounted, status, element, setElement };
2319
};

website/src/routes/docs/_layout.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ const menus: Menu[] = [
141141
label: "单选框组",
142142
path: "components/radio-group",
143143
},
144+
{
145+
label: "列表框",
146+
path: "components/listbox",
147+
},
144148
{
145149
label: "组合框",
146150
path: "components/combobox",

0 commit comments

Comments
 (0)