Skip to content

Commit

Permalink
♻️ Accordion 内部のコンテンツの高さが動的に変わる場合に対応 (#1605)
Browse files Browse the repository at this point in the history
  • Loading branch information
deatiger committed Apr 25, 2024
1 parent 999b822 commit 3053562
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-bears-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ingred-ui": minor
---

:lipstick: Accordion コンポーネント内のコンテンツの高さが可変の場合に対応
38 changes: 38 additions & 0 deletions src/components/Accordion/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as React from "react";
import { StoryObj } from "@storybook/react";
import Accordion, { AccordionProps } from "./Accordion";
import { useState } from "react";
import { ActionButton, Flex } from "..";

export default {
title: "Components/navigation/Accordion",
Expand Down Expand Up @@ -115,3 +117,39 @@ export const Controlled: StoryObj<AccordionProps> = {
);
},
};

export const DynamicHeight: StoryObj<AccordionProps> = {
render: (args) => {
const [rows, setRows] = useState<number>(1);
const handleAddRow = () => setRows((prevState) => prevState + 1);
const handleRemoveRow = () =>
setRows((prevState) => (prevState > 1 ? prevState - 1 : 1));
return (
<Flex display="flex" flexDirection="column" gap={2}>
<Flex display="flex" flexDirection="row" gap={2}>
<ActionButton color="primary" icon="add_line" onClick={handleAddRow}>
Add
</ActionButton>
<ActionButton
color="warning"
icon="delete_bin"
onClick={handleRemoveRow}
>
Remove
</ActionButton>
</Flex>
<Accordion
title={args.title}
disabled={args.disabled}
expanded={args.expanded}
>
{[...Array(rows)].map((_, index) => (
<div key={index} style={{ padding: "4px 8px" }}>
{args.children}
</div>
))}
</Accordion>
</Flex>
);
},
};
28 changes: 18 additions & 10 deletions src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, {
ReactNode,
forwardRef,
useEffect,
useMemo,
useRef,
useState,
} from "react";
Expand All @@ -24,19 +23,20 @@ const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(
) {
const theme = useTheme();
const [expandedState, setExpandedState] = useState(expanded);
const [height, setHeight] = useState<`${number}px` | "auto">("0px");
const [overflow, setOverflow] = useState<"hidden" | "visible">("hidden");
const accordionContentContainerRef = useRef<HTMLDivElement>(null);

const height = useMemo(() => {
if (expandedState && accordionContentContainerRef.current) {
return accordionContentContainerRef.current.scrollHeight;
}
return 0;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expandedState, accordionContentContainerRef.current]);

const handleChange = (event: React.SyntheticEvent, expanded: boolean) => {
setExpandedState(expanded);
onChange && onChange(event, expanded);
if (expanded) {
setHeight(`${accordionContentContainerRef.current?.scrollHeight ?? 0}px`);
} else {
setHeight(`${accordionContentContainerRef.current?.scrollHeight ?? 0}px`);
setOverflow("hidden");
setTimeout(() => setHeight("0px"), 100);
}
};

const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
Expand All @@ -49,6 +49,13 @@ const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(
}
};

const handleTransitionEnd = () => {
if (expandedState) {
setHeight("auto");
setOverflow("visible");
}
};

useEffect(() => {
setExpandedState(expanded);
}, [expanded]);
Expand Down Expand Up @@ -79,8 +86,9 @@ const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(
</Styled.AccordionTitle>
<Styled.AccordionContent
ref={accordionContentContainerRef}
expanded={expandedState}
height={height}
overflow={overflow}
onTransitionEnd={handleTransitionEnd}
>
{children}
</Styled.AccordionContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ exports[`Accordion component testing Accordion 1`] = `
</div>
</div>
<div
class="sc-ftvSup hGExZo"
height="0"
class="sc-ftvSup bxDIpT"
height="0px"
overflow="hidden"
>
Accordion Content
</div>
Expand Down Expand Up @@ -104,8 +105,9 @@ exports[`Accordion component testing Disable Accordion 1`] = `
</div>
</div>
<div
class="sc-ftvSup hGExZo"
height="0"
class="sc-ftvSup bxDIpT"
height="0px"
overflow="hidden"
>
Accordion Content
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Accordion/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ export const DropdownIndicator = styled.div`
`;

export const AccordionContent = styled.div<{
expanded: boolean;
height: number;
height: `${number}px` | "auto";
overflow: "hidden" | "visible";
}>`
height: ${({ height }) => height}px;
overflow: hidden;
height: ${({ height }) => height};
overflow: ${({ overflow }) => overflow};
transition: 0.3s all;
background-color: ${({ theme }) => theme.palette.white};
`;
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,9 @@ exports[`DualListBox component testing DualListBox candidateItems and selectedIt
</div>
</div>
<div
class="sc-papXJ NpijN"
height="0"
class="sc-papXJ gvktiO"
height="0px"
overflow="hidden"
>
<ul
class="sc-jqUVSM bBFcLq"
Expand Down

0 comments on commit 3053562

Please sign in to comment.