feat(components): collapse component styles in progress

This commit is contained in:
Junior Garcia 2022-10-20 23:41:40 -03:00
parent 462597b822
commit 1a0f81c006
6 changed files with 144 additions and 13 deletions

View File

@ -1,8 +1,14 @@
import {forwardRef} from "@nextui-org/system";
import {clsx, __DEV__} from "@nextui-org/shared-utils";
import {clsx, __DEV__, Expand} from "@nextui-org/shared-utils";
import {mergeProps} from "@react-aria/utils";
import {StyledCollapseItem, StyledCollapseItemButton} from "./collapse.styles";
import {
StyledCollapseItem,
StyledCollapseItemHeading,
StyledCollapseItemButton,
StyledCollapseItemTitle,
StyledCollapseItemIndicator,
} from "./collapse.styles";
import {UseCollapseItemProps, useCollapseItem} from "./use-collapse-item";
export interface CollapseItemProps<T extends object = {}>
@ -32,28 +38,32 @@ const CollapseItem = forwardRef<CollapseItemProps, "div">((props, ref) => {
isOpen={isOpen}
{...otherProps}
>
<h2 className="collapse-item-heading">
<StyledCollapseItemHeading className="nextui-collapse-item-heading">
<StyledCollapseItemButton
{...mergeProps(buttonProps, focusProps)}
ref={domRef}
className="collapse-item-button"
className="nextui-collapse-item-button"
disabled={isDisabled}
isFocusVisible={isFocusVisible}
>
{item.props.title}
<span
<StyledCollapseItemTitle className="nextui-collapse-item-title">
{item.props.title}
</StyledCollapseItemTitle>
<StyledCollapseItemIndicator
aria-hidden="true"
aria-label="collapse item indicator"
className="collapse-item-indicator"
className="nextui-collapse-item-indicator"
role="img"
>
{isOpen ? "🔽" : "▶️"}
</span>
</StyledCollapseItemIndicator>
</StyledCollapseItemButton>
</h2>
<div {...regionProps} className="collapse-item-content">
{item.props.children}
</div>
</StyledCollapseItemHeading>
<Expand isExpanded={isOpen}>
<div {...regionProps} className="nextui-collapse-item-content">
{item.props.children}
</div>
</Expand>
</StyledCollapseItem>
);
});

View File

@ -46,11 +46,29 @@ export const StyledCollapseItem = styled("div", {
},
});
export const StyledCollapseItemHeading = styled("h2", {});
export const StyledCollapseItemButton = styled(
"button",
{
textAlign: "start",
width: "100%",
display: "flex",
appearance: "none",
alignItems: "center",
padding: "$4 $6",
background: "transparent",
border: "none",
outline: "none",
cursor: "pointer",
},
cssFocusVisible,
);
export const StyledCollapseItemTitle = styled("div", {
flex: "1 1 0%",
textAlign: "left",
});
export const StyledCollapseItemIndicator = styled("span", {
flexShrink: 0,
});

View File

@ -34,6 +34,8 @@
"postpack": "clean-package restore"
},
"dependencies": {
"@nextui-org/system": "workspace:*",
"@nextui-org/use-real-shape": "workspace:*",
"deepmerge": "4.2.2"
},
"peerDependencies": {

View File

@ -0,0 +1,96 @@
import React, {useEffect, useRef, useState} from "react";
import {styled, HTMLNextUIProps} from "@nextui-org/system";
import {useRealShape} from "@nextui-org/use-real-shape";
export interface ExpandProps extends HTMLNextUIProps<"div"> {
isExpanded?: boolean;
animated?: boolean;
delay?: number;
}
const StyledExpand = styled("div", {
p: 0,
m: 0,
h: 0,
opacity: 0,
overflow: "hidden",
variants: {
isExpanded: {
true: {
opacity: 1,
},
},
},
});
export const Expand: React.FC<ExpandProps> = ({
css,
children,
delay = 200,
animated = true,
isExpanded = false,
...otherProps
}) => {
const [height, setHeight] = useState<string>(isExpanded ? "auto" : "0");
const [selfExpanded, setSelfExpanded] = useState<boolean>(isExpanded);
const contentRef = useRef<HTMLDivElement>(null);
const entryTimer = useRef<number>();
const leaveTimer = useRef<number>();
const resetTimer = useRef<number>();
const [state, updateShape] = useRealShape<HTMLDivElement>(contentRef);
useEffect(() => setHeight(`${state.height}px`), [state.height]);
useEffect(() => {
if (isExpanded === selfExpanded) return;
// show element or reset height.
// force an update once manually, even if the element does not change.
// (the height of the element might be "auto")
if (!isExpanded) {
updateShape();
setHeight(`${state.height}px`);
}
// show expand animation
entryTimer.current = window.setTimeout(() => {
setSelfExpanded(isExpanded);
clearTimeout(entryTimer.current);
}, 30);
// Reset height after animation
if (isExpanded) {
resetTimer.current = window.setTimeout(() => {
setHeight("auto");
clearTimeout(resetTimer.current);
}, delay);
} else {
leaveTimer.current = window.setTimeout(() => {
clearTimeout(leaveTimer.current);
}, delay / 2);
}
return () => {
clearTimeout(entryTimer.current);
clearTimeout(leaveTimer.current);
clearTimeout(resetTimer.current);
};
}, [isExpanded]);
return (
<StyledExpand
css={{
height: selfExpanded ? height : "0",
transition: animated
? `height ${delay}ms ease 0ms,
opacity ${delay * 1.5}ms ease 0ms;`
: "none",
...(css as any),
}}
isExpanded={selfExpanded}
{...otherProps}
>
<div ref={contentRef} className="nextui-expand-content">
{children}
</div>
</StyledExpand>
);
};

View File

@ -13,3 +13,4 @@ export * from "./functions";
export * from "./context";
export * from "./numbers";
export * from "./console";
export * from "./expand";

4
pnpm-lock.yaml generated
View File

@ -998,10 +998,14 @@ importers:
packages/utilities/shared-utils:
specifiers:
'@nextui-org/system': workspace:*
'@nextui-org/use-real-shape': workspace:*
clean-package: 2.1.1
deepmerge: 4.2.2
react: ^17.0.2
dependencies:
'@nextui-org/system': link:../../core/system
'@nextui-org/use-real-shape': link:../../hooks/use-real-shape
deepmerge: 4.2.2
devDependencies:
clean-package: 2.1.1